2012-04-27 137 views
4

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

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 

回答

3

this articleevalFunction构造解释:

(...)全球,内置eval功能在 呼叫者的范围评估代码。

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

而且根据this pagevoid刚刚返回undefined

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

+3

void评估全局范围内的代码。 – 2012-08-31 15:20:48

1
+0

'void'不评估全局范围内的代码。 'void expr'评估'expr'就像'expr'一样,它会在当前范围内执行。它根本不像'eval'或'Function',它将字符串评估为代码。 – Oriol 2016-12-25 02:14:12

0

值得注意的是,你完全错用了这些函数

  • void只是评估了一些表达和返回undefined。

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

    如果您担心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,它将被字符串化。构造函数将返回一个匿名函数,它将声明一个像参数一样的函数。没有用。

    如果您致电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语句。

相关问题