2012-01-20 94 views
49

刪除運算符的行爲似乎爲very complicated and there are many misunderstandings about what it actually does。對我來說,重新分配一些東西給undefined會更可靠地做你期望的事情。Javascript中刪除操作符的用途是什麼?

我從來沒見過Javascript實際用在非示例代碼中的delete關鍵字,我想知道它是否對任何事情都特別有用。 delete是否有任何目的不能通過重新分配給undefined來實現?是否在任何着名的庫(例如jQuery,dojo,骨幹等)中都使用它?

+0

'delete'的行爲根本不復雜。但它真的**不應該被稱爲'刪除'。 JavaScript在語法上類似於C++,使用運算符C++只能做一些*完全不同的事情,這有點像oops,導致了所有這些混亂。 (如果它被稱爲「刪除」,我敢打賭人們不會那麼困惑。) –

+0

http://perfectionkills.com/understanding-delete/ – Raghu

回答

61

刪除是否有任何目的不能通過重新分配給未定義?

是的。如果您想從原型中取消屏蔽屬性或導致in,hasOwnPropertyfor (...in...)未將該屬性記錄爲存在,則delete是合適的。

var set = {}; 

set._x = true; 

alert('_x' in set); // true 

set._x = undefined; 

alert('_x' in set); // true 

delete set._x; 

alert('_x' in set); // false 

編輯:作爲T.J.克勞德說明:

delete操作的目的是從物體完全刪除一個屬性,而屬性設置爲undefined只是將該屬性設置爲undefined

這很重要,在自己的權利,但是當你使用繼承,因爲如果Ø與P派生它也很重要,

var P = { prop: 42 }; 
var O = Object.create(P); // P is O's prototype. 

當您檢索O.prop,你會得到道具的價值如果O具有該名稱的屬性(即使其值未定義),則從O開始,但如果O根本沒有該屬性,則將從P.prop中檢索該值。

alert(O.prop); // "42" since O doesn't have its own prop, but P does. 
O.prop = undefined; 
alert(O.prop); // "undefined" since O has its own prop. 
delete O.prop; 
alert(O.prop); // "42" since the delete "unmasked" P.prop. 
0

那麼,你最終會得到一個包含值undefined的元素。關鍵不會消失。

9

如果你

delete Foo.Bar; 

它將刪除對象的Foo屬性欄完全

Foo.Bar = undefined 

僅僅設置欄屬性未定義和Foo.Bar仍然存在

1

你可以檢查答案以下鏈接Can I set variables to undefined or pass undefined as an argument?以非常詳細的方式解釋了區別。

摘要:

你當然可以指定未定義它,但不會刪除 變量。只有刪除object.property操作符真的會刪除 的東西。

刪除實際上是指屬性而不是變量。 瀏覽器將讓你脫離直接刪除變量,但它是 不是一個好主意,並且不會在ECMAScript第五版的嚴格 模式下工作。如果你想釋放對垃圾收集的引用,所以它可以是垃圾收集的 ,通常說變量= null。

19

正如Mike Samuel在他的回答中指出的那樣,刪除最常見的用法之一是將對象視爲將名稱與值相關聯的「屬性包」。 「這個名字現在被映射到一些假的值」和「這個名字根本沒有映射」在邏輯上是有區別的。 「刪除」達到後者。

這一切都很好理解。我想我可能會添加一個關於JScript 1.0到5.0引擎的有趣的歷史記錄。

在那些JScript原始Microsoft實現中,我們使用OLE自動化風格的IDispatch對象來實現expando對象。 IDispatch當然是通過將名稱與「dispatch id」關聯起來的,它只是一個整數。要動態調用,首先要求調度對象爲您提供與名稱關聯的調度ID,然後您說「現在調用與此ID關聯的方法,給定這些參數」。

這一切都很好。但是,IDispatch合同的其中一個要求是,在名稱的整個生命週期內,從名稱到發貨ID的映射爲穩定。因此,如果有人說「將屬性Foo添加到此對象」,那麼我們可能會決定該屬性Foo與該對象中的調度標識符0x1234關聯。從那一刻起,每次都要求對象發送「Foo」的調度標識符,即使Foo被刪除並且隨後再次添加,它也必須返回0x1234,這允許調用者維護自己的名稱/ dispid對的快速緩存,而不是每次調用時都必須詢問對象。

實際的結果是,「刪除」不以任何方式減輕該實現中對象的內存負擔!當你刪除一個屬性時(在原來的實現中),我們必須向該對象添加一些標記,表示該分派標識符已被刪除,但是如果該名稱再次出現,我們必須保留關於該名稱/標識符配對的所有信息。向對象添加大量屬性,然後刪除所有這些屬性不會縮小內存中的對象。當然,自從我的時間以來,JScript引擎當然被完全重寫了(除了我相信解析器和詞法分析器之外),所以我不知道引擎是否仍然存在這種不尋常的怪癖。這將是有趣的發現。

2

其他答案解釋delete關鍵字背後的動機。我想補充一點,到2017年,瀏覽器會在刪除屬性和將屬性設置爲undefined時解除分配內存

考慮這個例子(source of roughSizeOfObject()):

> var obj = {a:42,b:"b"}; roughSizeOfObject(obj) 
26 
> obj.a = undefined; roughSizeOfObject(obj) 
18 
> delete obj.a; roughSizeOfObject(obj) 
10 
> obj.b = undefined; roughSizeOfObject(obj) 
8 
> delete obj.b; roughSizeOfObject(obj) 
0 

的例子來自鉻61(64位)的控制檯(注意,在String所有字符在內部編碼爲16位無符號整數)。

相關問題