首页 > 解决方案 > 从代码中删除 eval 函数的使用

问题描述

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

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

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

但是,它使用 eval。有什么方法可以从中删除 eval 吗?

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

标签: javascriptevalprototype-programming

解决方案


是的,没有必要在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数组和also arguments.callee,它们不应该被使用,并且在严格模式下是不允许的。(严格模式是模块和类中的默认模式,并且将是任何进一步添加到语言的新范围的默认模式。)

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

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

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

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)来避免。

create使用的版本this避免显式命名构造函数:

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


推荐阅读