2012-05-17 38 views
15

我很難理解爲什麼在嚴格模式下,當在非限定標識符上使用delete時會出現語法錯誤。刪除非限定標識符時出現嚴格模式語法錯誤的原因?

在大多數情況下,它是有意義的......如果您以通常的方式使用var關鍵字聲明變量,然後嘗試對它們使用delete,那麼在非嚴格模式下它會默默地失敗,所以它會使感覺嚴格模式在這些情況下失敗並出現錯誤。

然而,也有情況下,您無法刪除標識符合格:

(function() { 

    // "use strict"; 

    var obj = Object.create({}, { bloop: { configurable: false } }); 

    delete obj.bloop; // throws TypeError in strict mode, silently fails in non-strict. 

    console.log('bloop' in obj); // true 

}()); 

嚴格模式必須在這裏做一個運行時檢查,因爲遇到此當一個TypeError異常。還有一些情況下,你可以成功在非嚴格模式下刪除不合格的標識符...

// "use strict"; 

window.bar = 6; 

console.log(typeof bar); // number 

delete bar; // works in non-strict, syntax error in strict! 

console.log(typeof bar); // undefined 

事實上,我的理解,你是否能夠刪除的東西(在非嚴格模式下)取決於內部[[Configurable]]屬性,並且與合格標識符無關。據我所知,有嚴格模式沒有辦法刪除非全局變量(如當地VO的屬性)配置:

(function() { 

    // "use strict"; 

    eval('var foo = 5;'); 

    console.log(typeof foo); // number 

    delete foo; // works in non-strict, SyntaxError in strict. 

    console.log(typeof foo); // undefined 

}()); 

所以,我的問題是,有什麼意義使用delete上的非限定標識符時拋出一個SyntaxError,如果該屬性不可配置,TypeError會拋出異常?這似乎是一種不必要的限制,並且在某些情況下似乎沒有任何解決方法,除非不使用嚴格模式(第三個示例)。任何人都可以解釋這個決定背後的動機嗎?


更新:我剛剛意識到我忽視了直接eval調用在嚴格模式下自己範圍的事實,而不是調用函數的範圍,所以在第三例foo不會受到嚴格的模式來定義。無論如何,運行時檢查仍然會捕獲這個問題,但它引出了一個問題:在嚴格模式下沒有辦法配置局部變量,就像我們在非嚴格模式下使用eval'd變量聲明? AFAIK是eval爲數不多的合法用途之一。

+0

調用究竟你的意思是什麼「(UN)合格標識」?我無法在規格中找到該術語。 – user123444555621

+1

@ Pumbaa80一個沒有點的標識符。 :) –

+0

@ Pumbaa80'(function(){「use strict」; var foo; delete foo;}())'... chromium:'SyntaxError:在嚴格模式下刪除一個不合格的標識符。' –

回答

6

你所談論的規格的Section 11.4.1, paragraph 5.a.

  1. Else, ref is a Reference to an Environment Record binding, so
    a. If IsStrictReference(ref) is true, throw a SyntaxError exception.
    b. Let bindings be GetBase(ref).
    c. Return the result of calling the DeleteBinding concrete method of bindings, providing GetReferencedName(ref) as the argument.

你所謂的「無保留意見的標識符」什麼是正式命名爲「環境記錄綁定」。

現在,你的問題。爲什麼拋出一個SyntaxError 5.c.反正會失敗?我想你自己回答了!

Strict mode must do a runtime check here, because a TypeError is thrown when this is encountered.

沒錯。但快速失敗總是更好。因此,如果有機會檢測到SyntaxError(在解析時間),應該採取該機會。

爲什麼?它可以節省您在發生錯誤時修復應用程序的麻煩。考慮可能會立即顯示錯誤的IDE,而不是幾個小時的調試。此外,這些限制對於優化的JIT編譯器可能是有利的。

+0

感謝您挖掘該規範參考。把它看作是一個調試助手或JIT優化器是有意義的。如果它被這樣使用,我想這是值得的,不能刪除你能夠以其他方式刪除的東西。 –

2

如果要以嚴格模式刪除對象。你必須明確提及有關財產訪問。還要注意,你如何調用這個函數很重要。如果不使用new運算符thisuse strict下未定義,並且不能使用以下方法。 例子:

 
'use strict' 
function func(){ 
    var self = this; 
    self.obj = {}; 
    self.obj.x = 'y' 

    console.log(self.obj); 
    delete self.obj // works 
    // delete obj // doesn't work 
    console.log(self.obj); 
} 

var f = new func(); 

刪除對象外的函數(關閉),你將有一個像

 
// same code as above 
delete f.obj 
+0

我不確定你的例子的重點。爲什麼我們爲'this'製作別名?除非你不使用'new',否則'delete obj'不會在非嚴格的情況下工作,但這看起來不像代碼的預期目的。除非我讀錯了,否則這種看起來像是對我的問題的反覆思考。無論如何+1,因爲我可能只是錯過了你的觀點;) –

+0

好吧,別名這是我的風格,你可以說。我使用它的原因是'this'在匿名函數下不可用,其中作爲變量'var self'將會可用 哦,關於'delete obj'在'new'下不起作用 - 我不知道我對JS比較陌生) 呵呵,我看錯了這個問題,沒關係。 – rda3mon

相關問題