是的,那里不需要eval。以下是您在现代环境中的做法 (ES2015+):
function Example(...args) {
if (!new.target) {
return new Example(...args);
}
// ...use `args` here, possibly destructuring to local meaningful names e.g.:
const [first, second] = args;
// ...
}
这避免了使用eval、arguments 伪数组以及arguments.callee,它们不应该被使用,并且在严格模式下是不允许的。 (严格模式是模块和类中的默认模式,并且将是任何进一步添加到语言的新范围的默认模式。)
如果您愿意,可以继续使用 arguments 伪数组:
function Example(first, second) {
if (!new.target) {
return new Example(...arguments);
}
// ...
}
FWIW,我强烈建议不要制作这样的双重用途功能。相反,当您不想使用new 时,请考虑使用class 语法和create 函数:
class Example {
constructor(biz, baz) {
// ...
}
static create(...args) {
return new Example(...args); // Or `return new this(...args);` or a couple of other choices.
}
}
如果您尝试执行Example(1, 2),则会自动抛出错误,因为class 构造函数不能像普通函数一样被调用。您可以改用Example.create(1, 2) 来避免new。
使用this 的create 版本避免显式命名构造函数:
static create(...args) {
return new this(...args);
}
这很有效,因为当您执行Example.create(1, 2) 时,在调用create 期间this 指的是Example. 但如果您在没有确保它被绑定的情况下绕过Example.create,它将不起作用。例如,const create = Example.create; create(1, 2); 会因new this(...) 而失败,但会与new Example(..) 一起工作。