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

Remove the use of eval function from code

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

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,我强烈建议不要 使函数像那样具有双重用途。相反,当您不想使用 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

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

    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(..).

一起工作

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