5

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
4

3 回答 3

4

本文中解释了evalFunction构造函数:

(…) 全局内置eval函数在调用者范围内评估代码

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

根据此页面void只需返回undefined

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

于 2012-04-27T01:37:39.070 回答
3

以下是评估差异的摘要:

  • void评估包含函数范围内的代码
  • eval评估包含函数范围内的字符串
  • Function在自己的范围内评估代码

和回报差异:

  • void总是返回未定义
  • eval返回执行代码的返回值
  • Function返回一个匿名函数

参考

于 2014-11-04T16:55:46.593 回答
1

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

  • void只是评估一些表达式并返回未定义。

    请注意,它是一个运算符而不是一个函数,因此无需将操作数包含在括号内。

    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())();stringify foo,将其解析为匿名函数,将匿名函数字符串化,然后再次将其解析为另一个匿名函数。请不要这样做。最后,调用将返回 undefined,因为其中没有 return 语句。

于 2016-12-25T02:08:07.440 回答