每次我创建一个类,我都需要做同样的无聊过程:
class Something {
constructor(param1, param2, param3, ...) {
this.param1 = param1;
this.param2 = param2;
this.param3 = param3;
...
}
}
有没有办法让它更优雅,更短?我使用Babel,因此允许使用一些ES7实验功能。也许装饰者可以帮忙吗?
每次我创建一个类,我都需要做同样的无聊过程:
class Something {
constructor(param1, param2, param3, ...) {
this.param1 = param1;
this.param2 = param2;
this.param3 = param3;
...
}
}
有没有办法让它更优雅,更短?我使用Babel,因此允许使用一些ES7实验功能。也许装饰者可以帮忙吗?
您可以使用 Object.assign
:
class Something {
constructor(param1, param2, param3) {
Object.assign(this, {param1, param2, param3});
}
}
这是一个ES2015(又名ES6)功能,分配 拥有可枚举的 一个或多个源对象到目标对象的属性。
当然,你必须两次编写arg名称,但至少它要短得多,如果你把它作为你的习语,那么当你想要在实例上有你想要的参数时,它会很好地处理它,例如你没有,例如:
class Something {
constructor(param1, param2, param3) {
Object.assign(this, {param1, param3});
// ...do something with param2, since we're not keeping it as a property...
}
}
示例:(Babel的REPL上的现场副本):
class Something {
constructor(param1, param2, param3) {
Object.assign(this, {param1, param2, param3});
}
}
let s = new Something('a', 'b', 'c');
console.log(s.param1);
console.log(s.param2);
console.log(s.param3);
输出:
一个 b C
不幸的是,你所能做的只是简单的事情 Object.assign
,但是如果你试图删除两次输入所有参数的冗余(一次在构造函数签名中,一次在赋值中),你可以做的就不多了。
也就是说,你可以像这样做一个黑客。虽然我不确定随之而来的努力和模糊处理是值得的。
var dependencies = ['param1', 'param2', 'param3'];
class Something {
constructor(...params) {
params.forEach((param, index) => this[dependencies[index]] = param);
}
}
var something = new Something('foo', 'bar', 'baz');
// something.param1 === 'foo'
这样,您将使用单个参数名称数组,然后在您的实例上创建属性时使用相同的数组作为引用 Something
。这种模式在Angular应用程序中可以很好地工作,在这种应用程序中,您尝试通过设置来缩小依赖关系名称 $inject
属性。
Something.$inject = dependencies;
PS - 欢迎来到我多余的古典语言 思想 当我成为JS开发人员时,我离开了:P
老实说,除非你真的需要实际类的形式,否则你应该只使用经典的对象文字。
编辑:我想如果你想要文字的简易性,你可以接受构造函数中的对象文字 和 实际阶级的形式。
class Something {
constructor(params) {
Object.keys(params).forEach((name) => this[name] = params[name]);
}
}
var something = new Something({
param1: 'foo',
param2: 'bar',
param3: 'baz'
});
但是现在你已经把一个类变成了一个动态类,它可以用任何属性实例化,有点像对象文字:P
通常我想要一个类,因为我想形式化对象并呈现一致且严格可测试的API。
我们可以在每个类中创建一个静态方法 arguments
object和一组名称,并返回一个可以使用分配给新实例的对象 Object.assign
。
用它来检查 巴贝尔REPL。
class Something {
static buildArgs (ctx, args, paramNames) {
let obj = {}
Array.from(args).forEach(function (arg, i) {
let name = paramNames[i] || i
obj[name] = args[i]
})
Object.assign(ctx, obj)
}
constructor () {
Something.buildArgs(this, arguments, [
'param1',
'param2'
]);
console.log(this)
}
}
new Something('one', 'two')
不可否认,增加了一种方法 buildArgs
意味着这个解决方案并不短,但是它的主体 constructor
我们也有这些优势:
上面的代码包含额外的参数(i >= paramNames.length
但是,如果这种行为是不合需要的,我们可以修改它,以便仍然解析这些行为,但不分配给实例:
class Something {
static buildArgs (ctx, args, paramNames) {
let obj = {instance: {}, extra: {}}
Array.from(args).forEach(function (arg, i) {
let name = paramNames[i] || i
if (name) {
obj.instance[name] = args[i]
} else {
obj.extra[i] = args[i]
}
})
Object.assign(ctx, obj)
}
constructor () {
let args = Something.buildArgs(this, arguments, ['param1', 'param2']);
// Do stuff with `args.extra`
}
}
或完全忽略:
static buildArgs (args, paramNames) {
let obj = {}
Array.from(args).forEach(function (arg, i) {
let name = paramNames[i]
if (name) obj[name] = args[i]
})
return obj
}