2012-04-27 152 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語句。

相關問題