在JavaScript中,可以使用eval()函數來解析字串中的JavaScript程式碼,並傳回對應的程式碼執行結果:
就本質而言,eval()是JavaScript全域物件的一個函數。例如,上述程式碼等價於:
不過在使用eval()語句時,一般都採用上述第一種做法,也即忽略全域物件直接使用eval()。
eval()的使用
基於以下兩個原因,除非確實需要,不然應盡量避免在程式碼中使用eval()語句:
1.從邏輯上來說,字串應該用於儲存程式運行過程中的內容、訊息,而不應該用於儲存具體的計算邏輯。
2.由於eval()參數為字串,而對於一段字串無法詞法進行,因此對於eval()呼叫語句,JavaScript解釋器無法進行最佳化。
eval()的回傳值
eval()的回傳值遵循下列規則:
1.如果eval()的參數不是字串,那麼eval()就會直接傳回參數。
2.如果eval()的參數是字串,那麼eval()將這個字串解析成程式碼後再執行,並傳回最後一行程式碼執行的結果。
3.如果字串無法解析成合法的程式碼,eval()將拋出SyntaxError錯誤。
4.如果字串能夠被解析成合法的程式碼,但是在執行這一程式碼過程中報錯,那麼這個錯誤會上報給eval()語句,並由eval()拋出。
console.log(eval("42 */ 2"));//SyntaxError
console.log(eval("42 * 2; 22 * 3;"));//66. eval returns the result of last expression/statement
console.log(eval("null.toString()"));//TypeError, exception in eval-ed code will be propagated outside eval().
變數環境(variable environment)
JavaScript中eval()有一個重要的特性:eval()參數字串中的程式碼可以存取外部程式碼中的變量,同時也可以將參數字串程式碼中新建的變數暴露給外部程式碼。也即,如果eval()參數字串可以合法解析,那麼JS會將解析後的程式碼替換掉eval()所在的那一行:
值得注意的是,實現上述特性的前提是eval()參數字串中的程式碼可以合法解析。除了程式碼語法正確外,JS還要求eval()參數字串中的程式碼必須「自成一體」:僅就參數字串中的程式碼而言,程式碼必須是有意義的。例如,無法將「return;」這樣的字串傳給eval()函數:
如果直接使用eval()函數,那麼eval()參數字串中的程式碼所存取的變數是eval()語句所在function的那些變量,也即eval()函數所使用的變數環境是“本地變數環境” 。如果不直接使用eval()函數,而是使用同樣指向eval()函數的新變量,那麼對應參數字串中的程式碼所存取的變數均為全域變量,也即eval()函數所使用的變量環境是「全域變數環境」:
不過,值得注意的是,IE6、7、8中的行為與此不同。在IE6、7、8中,即使eval()函數被重新命名,所使用的仍然是「本地變數環境」。