根據spec(附錄C),嚴格模式代碼幾乎不能做任何可能分配任何標識符的名稱,其名稱爲eval
。我可以理解,有人可能想要限制使用的實際eval
函數,但我沒有看到通過限制使用名稱來達到什麼目的?爲什麼EcmaScript 5嚴格模式會限制標識符'eval`
回答
我只能推測,但在我看來,ES5-strict是說eval
和arguments
應該被視爲原始語法,而不是標識符。這兩個特徵應該在語法層面上實施是合理的,因爲它們具有驚人的時髦魔術行爲,這些行爲不能由正常功能重現。
(尤其eval
可以寫入到調用它的函數的局部變量,並寫入arguments
奇怪的變化相對應的參數局部變量的值。儘管這種行爲似乎是在嚴格模式要離開,謝天謝地。 )
由於兼容性原因,ES5實際上不能使eval
和arguments
爲合成語法。所以他們儘量做到最接近,也就是說標識符arguments
總是指arguments
魔法,而標識符eval
總是專指eval
的魔法。
如果JS引擎可以確定一個函數是否包含魔法,它也可以改善優化的可能性。
bobince基本上是正確的。 (我在SpiderMonkey上工作,Mozilla的JS引擎,已經在其中實現了ES5的各個部分,並且在時間允許的情況下遵循ECMAScript討論。)您(實施者和讀者都)確實希望eval
成爲規範eval
,並且您希望arguments
成爲規範arguments
。使用嚴格模式,你可以主要得到這個。
但是我會指出,ES5的限制並不盡如人意。首先,需要矯正bobince咯,即使有嚴格的模式下,您不能確定eval
是原來eval
功能:
"use strict";
this.eval = function() { return "ohai"; };
eval("7 + 10"); // "ohai"
這是全球知名的對象錯誤(JS愛好者之間):該腳本使用一個跨腳本共享的全局對象,可命名和可修改,以解析名稱。如果你不能引用全局變量綁定的對象,你就不會有這個問題。 ES6可能會通過另一個選擇加入系統來解決這個問題(可能是MIME類型的帶外,但目前尚不清楚)始終限於整個腳本。
但即使沒有可命名的,易變的全局對象,你仍然有問題,因爲嚴格的模式可以作用域功能:
function outer()
{
var eval = function() { return "kthxbai"; };
function inner()
{
"use strict";
return eval("2 + 5");
}
return inner();
}
outer(); // "kthxbai"
即使在嚴格模式存在這些問題的存在,以後也不會因爲它可能會刪除全局對象,並無條件地執行嚴格的模式限制,所以最好一直等到ES6。
所以eval
在嚴格模式下仍然有點不可思議,因爲它可以引用not-eval。但處理這並不是什麼大問題 - 在運行時,實現可以檢查真實的eval
,如果這種失敗只是在語法碰巧使用eval
以外的名稱時執行。這要求專門處理像eval(...)
這樣的表達式。但是,無論如何,任何良好的實現都是這樣做的,因爲eval
的非靜態可觀察行爲(變異局部變量和參數,引入新變量[現在在嚴格模式下退化 - 嚴格模式中的變量聲明eval代碼是eval code]等等),所以它不是真正的負擔。
值得注意的是,這一切都不適用於arguments
作爲一種假的特殊形式。要麼你有一個函數範圍的方式嚴格模式,在這種情況下,你會看到是功能的arguments
而非arguments
分配外部範圍中,或您有它通過一個全球範圍內的方式,在這種情況下arguments
沒有特殊行爲。 (爲什麼在全球嚴格模式代碼中禁止arguments
突變?可能簡單,加上迫使開發人員將它們視爲更多特殊形式,但我不確定。)
您是否可能知道爲什麼在嚴格模式下仍然可以使用'eval''''arguments'作爲標籤名稱(http://stackoverflow.com/q/12557574/425275)? – 2012-09-24 00:59:12
我不知道,但基於在嚴格模式代碼中禁止'eval' /'arguments'作爲變量名稱的原因,我總是回答這個問題。 :-) – 2012-09-25 17:25:15
- 1. 爲什麼嚴格模式不會將標識符「eval」和「參數」限制爲標籤名稱?
- 2. Chrome 11抱怨沒有爲ECMAScript 5中的worker.js定義onmessage嚴格模式
- 3. 爲什麼doesen't javascript/ecmascript只使用嚴格的相等運算符?
- 4. ECMAScript 5爲什麼添加.bind()?
- 5. PHPUnit嚴格模式有什麼作用?
- 6. 嚴格限制VB.NET
- 7. 嚴格模式啓用時,MySQL會做什麼驗證?
- 8. (function eval(){})如果函數體在嚴格模式下會引發語法錯誤?
- 9. 爲什麼要使用格式標識符蟒蛇
- 10. XSD:「限制 - 模式」標籤的轉義字符是什麼
- 11. C標識符限制
- 12. 什麼是嚴格參照標誌的ECMA 5 262
- 13. Function.prototype.call改變此類型,嚴格模式外;爲什麼?
- 14. PHPUnit - 爲什麼PHPUnit似乎在嚴格模式下運行?
- 15. 標識符的限制?
- 16. 爲什麼solr搜索限制爲5個字符?
- 17. 嚴格限制一列不爲空
- 18. 刪除非限定標識符時出現嚴格模式語法錯誤的原因?
- 19. 爲什麼ActionScript 3有兩種編譯模式(嚴格與標準)?
- 20. 爲什麼HTMLParser忽略非嚴格模式下的開始標籤?
- 21. 標識符的ECMAScript規範2017年
- 22. eval()在方法中以嚴格模式運行嗎?
- 23. QUnit嚴格模式
- 24. Android嚴格模式
- 25. PHP 5和嚴格的標準錯誤
- 26. ECMAScript v 6什麼時候會成爲標準
- 27. 什麼是嚴格和非嚴格的模擬?
- 28. 參數在嚴格模式
- 29. 在嚴格模式下複製arguments.callee
- 30. 什麼是ECMAScript?
事實上,當我們在使用JScript.NET我們經常希望有一種方法可以絕對確保:(1)調用稱爲「eval」的東西調用eval,(2)調用不稱爲「eval」的東西不會調用eval。 ECMAScript的設計使得靜態確定非常困難,因此很難編寫優化編譯器。我已經在技術委員會工作了十年以上,所以他們不能說清楚他們的動機,但是我再次加入這個委員會,我肯定希望得到這樣的限制。 – 2010-08-17 23:41:45
ES5將'eval'修改爲「直接」或「間接」。直接評估僅通過形式爲'eval(...)'的表達式來進行。這種形式做它始終做的事情 - 引入新的綁定,變得邪惡,等等。間接評估*從不*影響本地範圍 - 相反,它被迫在全球範圍內行事。通過這種改變,你確切地知道在任何不包括直接評估的函數中會發生什麼 - 如果它確實如此,那麼你會很難去優化。在技術上ES3讓實現禁止間接評估,但很少有,也許JScript.NET不是一個。 – 2010-12-25 09:58:42
因此,繼續(用完字符),要求間接的'eval'影響全局範圍,否定了'eval'最有害的形式。 (直接'eval'不是很好,但至少可以檢測到,這樣可以防止它的不良行爲。)間接'eval'仍然可以修改全局範圍,true。但是一個函數中的任何東西都可能以幾乎不可能進行靜態預測的方式進行。對全球名稱的引用永遠不會像本地名稱那樣優化,而間接'eval'不會改變問題。只有ES6移除全局對象,如果它發生的話,可以做到這一點。 – 2010-12-25 10:08:57