【问题标题】:What's the difference between void, eval, and the Function constructor in JavaScript?JavaScript 中的 void、eval 和 Function 构造函数有什么区别?
【发布时间】:2012-05-07 18:48:48
【问题描述】:

void(document.body.innerText += 'hi')

eval(document.body.innerText +='\nbye')

Function(document.body.innerText += '\n!!!')

void(Function(function foo(){document.body.innerText += '\n>hi2'; return true}).toString())();

eval(Function(function foo(){document.body.innerText += '\nbye2'; return true}).toString())();

Function(Function(function foo(){document.body.innerText += '\n!!!2'; return true}).toString())();

在这些不同语句中执行代码的处理模型是什么?

void(alert('hi'))
undefined

eval(alert('hi'))
undefined

Function(alert('hi'))
function anonymous() {
  undefined
}

eval(Function(function foo(){return true}).toString())();
TypeError: undefined is not a function

void(Function(function foo(){return true}).toString())();
TypeError: string is not a function

Function(Function(function foo(){return true}).toString())();
undefined

【问题讨论】:

    标签: javascript eval void ecmascript-5 function-constructor


    【解决方案1】:

    this article 中解释了evalFunction 构造函数:

    (...) 全局,内置 eval 函数 在 a 范围内评估代码 来电者

    Function构造函数创建的函数内部执行的代码 并没有真正在全局范围内执行。但是,它不会在 本地范围也是如此,这可能会导致混淆。 Function 构造函数创建一个函数,其作用域链由 只不过是一个全局范围(在函数自己的激活之前 对象,当然)。通过创建的函数中包含的任何代码 Function构造函数在该函数的范围内进行评估,而不是在 全局范围。然而,代码几乎是全局执行的,因为 全局对象是作用域链中的下一个对象。

    而根据this pagevoid 只是返回undefined

    在许多语言中,void 是一种没有值的类型。在 JavaScript 中, void 是一个接受操作数并返回 undefined 的运算符。这 没有用,而且很混乱。避免void

    【讨论】:

      【解决方案2】:

      【讨论】:

      • void 不会评估全局范围内的代码。 void expr 评估 expr 就像单独使用 expr 一样,并且它发生在当前范围内。它根本不像 evalFunction,它们将字符串评估为代码。
      【解决方案3】:

      值得注意的是,您完全在滥用这些功能

      • void 只是计算一些表达式并返回 undefined。

        注意它是一个操作符而不是一个函数,所以不需要将操作符包裹在括号内。

        这仅在您担心undefined 可能被遮蔽或您想输入更少字符时才对获取 undefined 值有用。

        而不是

        var undef = void(document.body.innerText += 'hi')
        

        更好的使用

        document.body.innerText += 'hi';
        var undef = void 0;
        

        如果您不需要 undefined,请不要使用 void

      • eval 应该用字符串调用。它将该字符串评估为代码。确切的行为取决于您是在严格模式还是草率模式下调用它,以及它是直接调用还是间接调用。

        如果你不使用字符串调用它,它只会返回参数。

        在你的情况下,eval(document.body.innerText += '\nbye') 将:

        1. 运行document.body.innerText += '\nbye',返回新值,例如"hello\nbye"
        2. 将生成的文本评估为代码。这很可能会抛出。

        我几乎可以肯定eval(document.body.innerText +='\nbye') 不是你想要的,但这里有一个(不推荐的)反例:

        var myvar = 0;
        var bye = 123
        eval(document.body.innerText += '\nbye');
        console.log(myvar); // 123
        myvar =
      • Function 构造函数基本上类似于eval,但它创建一个函数而不是立即将字符串作为代码运行。

        document.body.innerText += '\n!!!' 不能返回一个有效的字符串,所以它只会抛出。

      • 那么你有这些功能的一些奇怪的组合。

        如果您将函数传递给Function 构造函数,它将被字符串化。 Function 构造函数将返回一个匿名函数,该函数将只声明一个类似于参数的函数。没意义。

        如果你调用toString,这会将匿名函数字符串化。

        然后,void(Function(function foo(){document.body.innerText += '\n>hi2'; return true}).toString())(); 将尝试调用此字符串化。但是字符串是不可调用的。错误。

        eval(Function(function foo(){document.body.innerText += '\nbye2'; return true}).toString())(); 将评估字符串化。只是为什么?但是函数声明不返回值,所以你只会得到 undefined,这是不可调用的。错误。

        Function(Function(function foo(){document.body.innerText += '\n!!!2'; return true}).toString())(); 会将foo 字符串化,解析为匿名函数,再将匿名函数字符串化,然后再次解析为另一个匿名函数。请不要这样做。最后,调用将返回 undefined,因为其中没有 return 语句。

      【讨论】:

        猜你喜欢
        • 2017-12-05
        • 1970-01-01
        • 2021-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多