从代码中删除 eval 函数的使用

问题描述

我最喜欢使用的一段代码是:

if (!(eval("this instanceof "+arguments.callee.name)))
  return eval("new "+arguments.callee.name+"(...arguments)");

这段代码允许函数原型在设置时创建自己,就像将自己的结果作为常规函数一样。 (删除了对函数原型键入“new”的要求)

然而,它使用 eval。 有什么办法可以去掉 eval 吗?

另外,有没有办法进一步缩短它?

解决方法

是的,那里不需要 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;
    // ...
}

这避免了使用 evalarguments 伪数组,以及 arguments.callee,它不应该被使用并且在严格模式下是不允许的。 (严格模式是模块和类中的默认模式,并且将是添加到该语言的任何其他新作用域中的默认模式。)

如果您愿意,可以继续使用 arguments 伪数组:

function Example(first,second) {
    if (!new.target) {
        return new Example(...arguments);
    }
    // ...
}

FWIW,我强烈建议不要将这样的功能双重使用。相反,当您不想使用 class 时,请考虑使用 create 语法和 new 函数:

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 构造函数不能像普通函数一样被调用。您可以使用 new 来避免 Example.create(1,2)

使用 createthis 版本避免显式命名构造函数:

    static create(...args) {
        return new this(...args);
    }

这是有效的,因为当您执行 Example.create(1,2) 时,在调用 create 期间 this 指的是 Example. 但如果您确实通过 {{1}周围没有确保它的绑定。例如,Example.create 会因 const create = Example.create; create(1,2); 而失败,但会与 new this(...) 一起工作。

,

if(!new.target)return new this[arguments.callee.name](...arguments);