在看別的大牛的博客時,總會提示不要使用eval,一直沒有深入研究為什么,總以為是安全性問題,也沒有去研究eval的其他的注意事項,
最近在看“JavaScript秘密花園”博客時,碰到這個問題,參考並做了一些總結。
首先,eval函數的作用是在當前作用域中執行一段JavaScript代碼字符串,如下代碼段1:
//代碼段1
var foo = 1; function test() { var foo = 2; eval('foo = 3'); return foo; } test(); // 3 foo; // 1
但是 eval
只在被直接調用並且調用函數就是 eval
本身時,才在當前作用域中執行,如何理解這句話呢,以上的代碼就是對紅色背景部分的描述,
以下代碼段2就不屬於對於eval的直接調用了,代碼段2如下:
//代碼段2 var foo = 1; function test() { var foo = 2; var bar = eval; bar('foo = 3'); return foo; } test(); // 2 foo; // 3
上面的代碼等價於在全局作用域中調用 eval
,和下面兩種寫法(代碼段3)效果一樣:
//代碼段3 // 寫法一:直接調用全局作用域下的 foo 變量 var foo = 1; function test() { var foo = 2; window.foo = 3; return foo; } test(); // 2 foo; // 3 // 寫法二:使用 call 函數修改 eval 執行的上下文為全局作用域 var foo = 1; function test() { var foo = 2; eval.call(window, 'foo = 3'); return foo; } test(); // 2 foo; // 3
在任何情況下我們都應該避免使用 eval
函數。99.9% 使用 eval
的場景都有不使用 eval
的解決方案。
偽裝的 eval
定時函數 setTimeout
和 setInterval
都可以接受字符串作為它們的第一個參數。 這個字符串總是在全局作用域中執行,因此 eval
在這種情況下沒有被直接調用。
安全問題
eval
也存在安全問題,因為它會執行任意傳給它的代碼, 在代碼字符串未知或者是來自一個不信任的源時,絕對不要使用 eval
函數。
結論
絕對不要使用 eval
,任何使用它的代碼都會在它的工作方式,性能和安全性方面受到質疑。 如果一些情況必須使用到 eval
才能正常工作,首先它的設計會受到質疑,這不應該是首選的解決方案, 一個更好的不使用 eval
的解決方案應該得到充分考慮並優先采用。