今天在看prototype程式碼時發現了delete這個操作符
unset: function(key) {
var value = this._object[key];
delete this._object[key];
return value;
}
查了一下手冊,
delete 運算子從物件中刪除一個屬性,或從陣列中刪除一個元素。
delete expression
expression 參數是一個有效的JScript 表達式,通常是一個屬性名稱或陣列元素。
說明如果expression 的結果是一個對象,且在expression 中指定的屬性存在,而該對象又不允許它被刪除,則傳回false。
在所有其他情況下,傳回true。
看到「從陣列中刪除一個元素」感覺不錯,可ff裡試了一下,似乎只能刪除那個元素的值,而不是元素本身。不過從物件中刪除一個屬性是可以的。
又google了一下,發現有一篇文章講得很詳細,轉載過來以免忘記:
標題:Javascript的變數與delete操作符版權聲明:可以任意轉載,但轉載時必須標明原作者charlee、原始連結http://tech.idv2.com/2008/01/09/javascript-variables-and-delete -operator/以及本聲明。
內容:
剛剛看到一篇好文(原文連結),對Javascript中的delete操作符分析得很透徹。在這裡簡單地介紹一下內容。
雖然是一個小小的delete操作符,其行為卻異常複雜。
Javascript的變數
delete操作符刪除的物件對變數執行delete的情況能刪除的屬性和不能刪除的屬性能刪除的變數和不能刪除的變數
delete的回傳值
---------------------------------------------------- ----------------------------------
Javascript的變數實際上Javascript中,變數= 物件屬性,這是因為Javascript 在執行腳本之前會建立一個Global對象,所有的全域變數都是這個Global物件的屬性,執行函數時也會建立一個Activation對象,所有的局部變數都是這個Activation物件的屬性。如下例:
var global = 42;this.global; // 42, 可以透過this來存取Global物件this.global2 = 12;global2; // 12function foo() { var local = 36; // 不過無法直接存取Activation , // 因此無法透過foo.local 的方式來存取local變數}delete操作符刪除的對象
C++中也有delete操作符,它刪除的是指標所指向的物件。例如:
// C++class Object {public: Object *x;}Object o;ox = new Object();delete ox; // 上一行new的Object物件會被釋放但Javascript的delete與C++不同,它不會刪除ox指向的對象,而是刪除ox屬性本身。
// Javascriptvar o = {};ox = new Object();delete ox; // 上一行new的Object物件依然存在ox; // undefined,o的名稱為x的屬性被刪除了在實際的Javascript中, delete ox之後,Object對象會因為失去了引用而被垃圾回收,所以delete ox也就「相當於」刪除了ox所指向的對象,但這個動作並不是ECMAScript標準,也就是說,即使某個實現完全不刪除Object對象,也不算違反ECMAScript標準。
「刪除屬性而不是刪除物件」這一點,可以透過以下的程式碼來確認。
var o = {};var a = { x: 10 };oa = a;delete oa; // oa屬性被刪除oa; // undefineda.x; // 10, 因為{ x: 10 } 物件依然被a引用,所以不會被回收另外,delete ox 也可以寫作delete o["x"],兩者效果相同。
對變數執行delete的情況由於變數也是Global 或是Activation 物件的屬性,所以對變數的delete操作也是同樣的結果。
var global = 42;delete global; // 刪除Global.globalfunction foo() { var local = 36; delete local; // 刪除Activation.local}能刪除的屬性和不能刪除的屬性並不是所有的屬性都能被delete。例如,prototype中宣告的屬性就無法被delete:
function C() { this.x = 42; }C.prototype.x = 12;var o = new C();ox; // 42, 建構子中定義的o.xdelete ox;ox; // 12, prototype中定義的ox,即使再次執行delete ox也不會被刪除物件的預定義屬性也無法刪除。 可以認為這類屬性帶有DontDelete的特性。
var re = /abc/i;delete re.ignoreCase;re.ignoreCase; // true, ignoreCase無法刪除能刪除的變數和不能刪除的變數透過var宣告的變數和透過function宣告的函數擁有DontDelete特性,無法被刪除。
var x = 36;delete x;x; // 36, x沒有被刪除y = 12;delete y;y; // undefinedfunction foo() { return 42; }delete foo;foo(); // 42但是有一點例外,就是透過eval 執行的程式碼中,透過var宣告的變數雖然與正常的var宣告變數同屬於Global對象,但它們不具有DontDelete特性,能被刪除。
eval("var x = 36;");x; // 42delete x;x; // undefined但是這也有一點例外,eval的程式碼中的函數內透過var定義的變數具有DontDelete,不能被刪除eval(" (function() { var x = 42; delete x; return x; })();");// 傳回42delete的回傳值
delete是普通運算符,會回傳true或false。規則為:當被delete的物件的屬性存在且擁有DontDelete時傳回false,否則傳回true。這裡的一個特點就是,物件屬性不存在時也會回傳true,所以回傳值並非完全等同於刪除成功與否。
function C() { this.x = 42; }C.prototype.y = 12;var o = new C();delete ox; // trueo.x; // undefined"x" in o; // false/ / ox存在且沒有DontDelete,傳回truedelete oy; // trueo.y; // 12// o自己沒有oy屬性,所以回傳true// 從這裡也可以看到prototype鏈的存在,物件本身屬性和prototype屬性是不同的delete o; // false// Global.o擁有DontDelete特性所以返回falsedelete undefinedProperty; // true// Global沒有名為undefinedProperty的屬性因此返回truedelete 42; // true// 42不是屬性所以返回true 。有的實作會拋出異常(違反ECMAScript標準)var x = 24;delete x++; // truex; // 25// 被刪除的是x++的回傳值(24),不是屬性,所以回傳true