每次我创建一个类,都需要做同样无聊的流程:
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)功能,它将一个或多个源对象的可枚举属性分配给目标对象。
当然,需要将参数名称写两次,但至少它更短,如果您将其确定为自己的习惯用语,则处理实例上确实需要的参数和不需要的参数时会很好,例如:
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);
输出:
a b c
arguments
对于参数有命名属性吗?我的意思是,除了 0
、1
和 2
之外还有其他名称吗?如果是这样的话,那对我来说是新的。 - T.J. Crowder不幸的是,你所能做的只有一些简单的事情,例如 Object.assign
。但是,如果你试图消除在构造函数签名和赋值中重复输入所有参数的冗余,那么你几乎没有什么可做的。
话虽如此,你可以尝试像这样的 hack。虽然我不确定这样做所需的努力和混淆程度是否值得。
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.callee.toString().match(/^function.*?\((.*?)\)/)[1].split(/,\s*/) }
- Touffyclass 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
}