JavaScript 中的 void、eval 和 Function 构造函数有什么区别?

What's the difference between void, eval, and the Function constructor in JavaScript?

本文关键字:构造函数 什么 区别 Function 中的 void eval JavaScript      更新时间:2023-09-26

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

在本文中,解释了构造函数evalFunction

(...全局内置 eval 函数计算 来电者

从构造函数中创建的函数Function执行的代码 实际上不会在全局范围内执行。但是,它不会在 局部范围,这可能会导致混乱。 Function构造函数创建一个函数,其作用域链由 只有一个全局范围(前面是函数自己的激活 当然是对象)。通过 创建的函数中包含的任何代码 Function构造函数在该函数的范围内计算,而不是在 全球范围。但是,这几乎就像代码全局执行一样,因为 全局对象是作用域链中的下一个对象。

根据此页面,void只返回undefined

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

以下是评估差异的摘要:

  • void计算包含函数作用域中的代码
  • eval计算包含函数作用域中的字符串
  • Function在其自己的范围内评估代码

和返回差异:

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

引用

  • JS101:函数构造函数
  • JSLint 错误解释:函数构造函数是 eval
  • 埃瓦尔有多邪恶
  • 通过函数构造函数创建的函数的 [[范围]]
  • 通过 eval() 和 new Function() 评估 JavaScript 代码
  • Gmail for Mobile HTML5系列:减少启动延迟 - 官方Google Code博客
  • 通过 Eval() 更快地加载 – SproutCore
  • (下)将 JavaScript 作为字符串加载 |高性能网站
  • JavaScript 中的表达式与语句 - Dr. Axel Rauschmayer
  • JavaScript 中的 void 运算符
值得注意的是

您完全滥用了这些功能

  • void只是计算一些表达式并返回未定义的表达式。

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

    仅当您担心值可能被阴影化或想要键入较少的字符时,这才可用于获取未定义的值undefined

    而不是

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

    更好地使用

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

    如果你不需要未定义,就不要使用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())();将评估字符串化。为什么呢?但是函数声明不返回值,所以你只会得到未定义,这是不可调用的。错误。

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