2009-12-19 58 views

回答

7

我只能推測,但在我看來,ES5-strict是說evalarguments應該被視爲原始語法,而不是標識符。這兩個特徵應該在語法層面上實施是合理的,因爲它們具有驚人的時髦魔術行爲,這些行爲不能由正常功能重現。

(尤其eval可以寫入到調用它的函數的局部變量,並寫入arguments奇怪的變化相對應的參數局部變量的值。儘管這種行爲似乎是在嚴格模式要離開,謝天謝地。 )

由於兼容性原因,ES5實際上不能使evalarguments爲合成語法。所以他們儘量做到最接近,也就是說標識符arguments總是指arguments魔法,而標識符eval總是專指eval的魔法。

如果JS引擎可以確定一個函數是否包含魔法,它也可以改善優化的可能性。

+4

事實上,當我們在使用JScript.NET我們經常希望有一種方法可以絕對確保:(1)調用稱爲「eval」的東西調用eval,(2)調用不稱爲「eval」的東西不會調用eval。 ECMAScript的設計使得靜態確定非常困難,因此很難編寫優化編譯器。我已經在技術委員會工作了十年以上,所以他們不能說清楚他們的動機,但是我再次加入這個委員會,我肯定希望得到這樣的限制。 – 2010-08-17 23:41:45

+0

ES5將'eval'修改爲「直接」或「間接」。直接評估僅通過形式爲'eval(...)'的表達式來進行。這種形式做它始終做的事情 - 引入新的綁定,變得邪惡,等等。間接評估*從不*影響本地範圍 - 相反,它被迫在全球範圍內行事。通過這種改變,你確切地知道在任何不包括直接評估的函數中會發生什麼 - 如果它確實如此,那麼你會很難去優化。在技​​術上ES3讓實現禁止間接評估,但很少有,也許JScript.NET不是一個。 – 2010-12-25 09:58:42

+0

因此,繼續(用完字符),要求間接的'eval'影響全局範圍,否定了'eval'最有害的形式。 (直接'eval'不是很好,但至少可以檢測到,這樣可以防止它的不良行爲。)間接'eval'仍然可以修改全局範圍,true。但是一個函數中的任何東西都可能以幾乎不可能進行靜態預測的方式進行。對全球名稱的引用永遠不會像本地名稱那樣優化,而間接'eval'不會改變問題。只有ES6移除全局對象,如果它發生的話,可以做到這一點。 – 2010-12-25 10:08:57

10

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突變?可能簡單,加上迫使開發人員將它們視爲更多特殊形式,但我不確定。)

+0

您是否可能知道爲什麼在嚴格模式下仍然可以使用'eval''''arguments'作爲標籤名稱(http://stackoverflow.com/q/12557574/425275)? – 2012-09-24 00:59:12

+0

我不知道,但基於在嚴格模式代碼中禁止'eval' /'arguments'作爲變量名稱的原因,我總是回答這個問題。 :-) – 2012-09-25 17:25:15

相關問題