Javascript中的delete介紹
更新時(shí)間:2012年09月02日 21:36:12 作者:
關(guān)于JavaScript中的Delete一直沒(méi)有弄的很清楚,最近看到兩篇這方面的文章,現(xiàn)對(duì)兩文中部分內(nèi)容進(jìn)行翻譯(內(nèi)容有修改和添加,順序不完全一致,有興趣推薦看原文),希望能對(duì)大家有所幫助
一、問(wèn)題的提出
我們先來(lái)看看下面幾段代碼,要注意的是,以下代碼不要在瀏覽器的開發(fā)者工具(如FireBug、Chrome Developer tool)中運(yùn)行,原因后面會(huì)說(shuō)明:
為什么我們可以刪除對(duì)象的屬性:
var o = { x: 1 };
delete o.x; // true
o.x; // undefined
但不以刪除像這樣聲明的變量:
var x = 1;
delete x; // false
x; // 1
也不能刪除像這樣定義的函數(shù):
function x(){}
delete x; // false
typeof x; // "function"
注意:當(dāng)delete操作符返回true時(shí)表示可以刪除,返回false表示不能刪除
要理解這一點(diǎn),我們首先需要掌握像變量實(shí)例化和屬性特性這樣的概念--遺憾的是這些內(nèi)容在一些javascript的書中很少講到。理解它們并不難,如果你不在乎它們?yōu)槭裁催@么運(yùn)行,你可以隨意的跳過(guò)這一部分。
二、代碼類型
在ECMAScript中有三種類型的可執(zhí)行代碼:Global code(全局代碼)、Function code(函數(shù)代碼)和 Eval code(放在Eval中執(zhí)行的代碼)。
var x=1;//Global code
function test(){
var y=2;//Function Code
eval("var z=3");//Eval Code in Function
}
eval("function evalTest(){}");//Eval Code in Global
三、執(zhí)行上下文
當(dāng)ECMAScript 代碼執(zhí)行時(shí),它總是在一定的上下文中運(yùn)行,執(zhí)行上下文是一個(gè)有點(diǎn)抽象的實(shí)體,它有助于我們理解作用域和變量實(shí)例化如何工作的。對(duì)于三種類型的可執(zhí)行代碼,每個(gè)都有執(zhí)行的上下文。當(dāng)一個(gè)函數(shù)執(zhí)行時(shí),可以說(shuō)控制進(jìn)入到函數(shù)代碼(Function code)的執(zhí)行上下文。全局代碼執(zhí)行時(shí),進(jìn)入到全局代碼(Global code)的執(zhí)行上下文。
正如你所見,執(zhí)行上下文邏輯上來(lái)自一個(gè)棧。首先可能是有自己作用域的全局代碼,代碼中可能調(diào)用一個(gè)函數(shù),它有自己的作用域,函數(shù)可以調(diào)用另外一個(gè)函數(shù),等等。即使函數(shù)遞歸地調(diào)用它自身,每一次調(diào)用都進(jìn)入一個(gè)新的執(zhí)行上下文。
四、Activation object(激活對(duì)象)/Variable object(變量對(duì)象)
每一個(gè)執(zhí)行上下文在其內(nèi)部都有一個(gè)Variable Object。與執(zhí)行上下文類似,Variable object是一個(gè)抽象的實(shí)體,用來(lái)描述變量實(shí)例化的機(jī)制。有趣的是在代碼中聲明的變量和函數(shù)實(shí)際上被當(dāng)作這個(gè)變量對(duì)象的屬性被添加。
當(dāng)進(jìn)入全局代碼的執(zhí)行上下文時(shí),一個(gè)全局對(duì)象用作變量對(duì)象。這也正是為什么在全局范圍中聲明的變量或者函數(shù)變成了全局對(duì)象的屬性。
/* remember that `this` refers to global object when in global scope */
var GLOBAL_OBJECT = this;
var foo = 1;
GLOBAL_OBJECT.foo; // 1
foo === GLOBAL_OBJECT.foo; // true
function bar(){}
typeof GLOBAL_OBJECT.bar; // "function"
GLOBAL_OBJECT.bar === bar; // true
全局變量變成了全局對(duì)象的屬性,但是,那些在函數(shù)代碼(Function code)中定義的局部變量又會(huì)如何呢?行為其實(shí)很相似:它成了變量對(duì)象的屬性。唯一的差別在于在函數(shù)代碼(Function code)中,變量對(duì)象不是全局對(duì)象,而是所謂的激活對(duì)象(Activation object)。每次函數(shù)代碼(Function code)進(jìn)入執(zhí)行作用域時(shí),就會(huì)創(chuàng)建一個(gè)激活對(duì)象(Activation object)。
不僅函數(shù)代碼(Function code)中的變量和函數(shù)成為激活對(duì)象的屬性,而且函數(shù)的每一個(gè)參數(shù)(與形參相對(duì)應(yīng)的名稱)和一個(gè)特定Arguments 對(duì)象也是。注意,激活對(duì)象是一種內(nèi)部機(jī)制,不會(huì)被程序代碼真正訪問(wèn)到。
(function(foo){
var bar = 2;
function baz(){}
/*
In abstract terms,
Special `arguments` object becomes a property of containing function's Activation object:
ACTIVATION_OBJECT.arguments; // Arguments object
...as well as argument `foo`:
ACTIVATION_OBJECT.foo; // 1
...as well as variable `bar`:
ACTIVATION_OBJECT.bar; // 2
...as well as function declared locally:
typeof ACTIVATION_OBJECT.baz; // "function"
*/
})(1);
最后,在Eval 代碼(Eval code)中聲明的變量作為正在調(diào)用的上下文的變量對(duì)象的屬性被創(chuàng)建。Eval 代碼(Eval code)只使用它正在被調(diào)用的哪個(gè)執(zhí)行上下文的變量對(duì)象。
var GLOBAL_OBJECT = this;
/* `foo` is created as a property of calling context Variable object,
which in this case is a Global object */
eval('var foo = 1;');
GLOBAL_OBJECT.foo; // 1
(function(){
/* `bar` is created as a property of calling context Variable object,
which in this case is an Activation object of containing function */
eval('var bar = 1;');
/*
In abstract terms,
ACTIVATION_OBJECT.bar; // 1
*/
})();
五、屬性特性
現(xiàn)在變量會(huì)怎樣已經(jīng)很清楚(它們成為屬性),剩下唯一的需要理解的概念是屬性特性。每個(gè)屬性都有來(lái)自下列一組屬性中的零個(gè)或多個(gè)特性--ReadOnly, DontEnum, DontDelete 和Internal,你可以認(rèn)為它們是一個(gè)標(biāo)記,一個(gè)屬性可有可無(wú)的特性。為了今天討論的目的,我們只關(guān)心DontDelete 特性。
當(dāng)聲明的變量和函數(shù)成為一個(gè)變量對(duì)象的屬性時(shí)--要么是激活對(duì)象(Function code),要么是全局對(duì)象(Global code),這些創(chuàng)建的屬性帶有DontDelete 特性。但是,任何明確的(或隱含的)創(chuàng)建的屬性不具有DontDelete 特性。這就是我們?yōu)槭裁匆恍傩阅軇h除,一些不能。
var GLOBAL_OBJECT = this;
/* `foo` is a property of a Global object.
It is created via variable declaration and so has DontDelete attribute.
This is why it can not be deleted. */
var foo = 1;
delete foo; // false
typeof foo; // "number"
/* `bar` is a property of a Global object.
It is created via function declaration and so has DontDelete attribute.
This is why it can not be deleted either. */
function bar(){}
delete bar; // false
typeof bar; // "function"
/* `baz` is also a property of a Global object.
However, it is created via property assignment and so has no DontDelete attribute.
This is why it can be deleted. */
GLOBAL_OBJECT.baz = 'blah';
delete GLOBAL_OBJECT.baz; // true
typeof GLOBAL_OBJECT.baz; // "undefined"
六、內(nèi)置屬性和DontDelete
一句話:屬性中一個(gè)獨(dú)特的特性(DontDelete)控制著這個(gè)屬性是否能被刪除。注意,對(duì)象的內(nèi)置屬性(即對(duì)象的預(yù)定義屬性)有DontDelete 特性,因此不能被刪除。特定的Arguments 變量(或者,正如我們現(xiàn)在了解的,激活對(duì)象的屬性),任何函數(shù)實(shí)例的length屬性也擁有DontDelete 特性。
(function(){
/* can't delete `arguments`, since it has DontDelete */
delete arguments; // false
typeof arguments; // "object"
/* can't delete function's `length`; it also has DontDelete */
function f(){}
delete f.length; // false
typeof f.length; // "number"
})();
與函數(shù)參數(shù)相對(duì)應(yīng)的創(chuàng)建的屬性也有DontDelete 特性,因此也不能被刪除。
(function(foo, bar){
delete foo; // false
foo; // 1
delete bar; // false
bar; // 'blah'
})(1, 'blah');
七、未聲明的賦值
簡(jiǎn)單地就是未聲明的賦值在一個(gè)全局對(duì)象上創(chuàng)建一個(gè)可刪除的屬性。
var GLOBAL_OBJECT = this;
/* create global property via variable declaration; property has DontDelete */
var foo = 1;
/* create global property via undeclared assignment; property has no DontDelete */
bar = 2;//可理解為 window.bar=2; 根據(jù)上面的第五點(diǎn)是可以刪除的
delete foo; // false
typeof foo; // "number"
delete bar; // true
typeof bar; // "undefined"
請(qǐng)注意,DontDelete特性是在屬性創(chuàng)建的過(guò)程中確定的,后來(lái)的賦值不會(huì)修改現(xiàn)有屬性已經(jīng)存在的特性,理解這一點(diǎn)很重要。
/* `foo` is created as a property with DontDelete */
function foo(){}
/* Later assignments do not modify attributes. DontDelete is still there! */
foo = 1;
delete foo; // false
typeof foo; // "number"
/* But assigning to a property that doesn't exist,
creates that property with empty attributes (and so without DontDelete) */
this.bar = 1;
delete bar; // true
typeof bar; // "undefined"
八、Eval code
在Eval中創(chuàng)建的變量或方法比較特別,沒(méi)有DontDelete特性,也就是說(shuō)可以刪除。
eval("var x = 1;");
console.log(x); // 1
delete x;
console.log(typeof x); // undefined
eval("function test(){ var x=1; console.log(delete x);/* false */;return 1;}");
console.log(test()); // 1
delete test;
console.log(typeof test); // undefined
注意,這里說(shuō)的在Eval中創(chuàng)建的變量或方法不包括方法內(nèi)部的變量或方法,如上面代碼中的紅色部分,仍然跟之前講的一致:不能被刪除。
九、FireBug的困惑
我們看一段在FireBug中執(zhí)行的代碼結(jié)果:
var x=1;
delete x;
console.log(typeof x);//undefined
function y(){
var z=1;
console.log(delete z);//false
}
y();
delete y;
console.log(typeof y);//undefined
這明明是違反上述規(guī)則的,但跟上面第八點(diǎn)對(duì)比后發(fā)現(xiàn),這正在代碼在eval中執(zhí)行的效果。雖然沒(méi)有證實(shí),但我猜測(cè)FireBug(Chrome Developer tool)中控制臺(tái)代碼是用eval執(zhí)行的。
所以,當(dāng)大家在測(cè)試JS代碼時(shí),如果涉及到當(dāng)前上下文環(huán)境時(shí)特別要注意。
十、delete操作符刪除的對(duì)象
C++中也有delete操作符,它刪除的是指針?biāo)赶虻膶?duì)象。例如:
class Object {
public:
Object *x;
}
Object o;
o.x = new Object();
delete o.x; // 上一行new的Object對(duì)象將被釋放
但Javascript的delete與C++不同,它不會(huì)刪除o.x指向的對(duì)象,而是刪除o.x屬性本身。
var o = {};
o.x = new Object();
delete o.x; // 上一行new的Object對(duì)象依然存在
o.x; // undefined,o的名為x的屬性被刪除了
在實(shí)際的Javascript中,delete o.x之后,Object對(duì)象會(huì)由于失去了引用而被垃圾回收, 所以delete o.x也就“相當(dāng)于”刪除了o.x所指向的對(duì)象,但這個(gè)動(dòng)作并不是ECMAScript標(biāo)準(zhǔn), 也就是說(shuō),即使某個(gè)實(shí)現(xiàn)完全不刪除Object對(duì)象,也不算是違反ECMAScript標(biāo)準(zhǔn)。
“刪除屬性而不是刪除對(duì)象”這一點(diǎn),可以通過(guò)以下的代碼來(lái)確認(rèn)。
var o = {};
var a = { x: 10 };
o.a = a;
delete o.a; // o.a屬性被刪除
o.a; // undefined
a.x; // 10, 因?yàn)閧 x: 10 } 對(duì)象依然被 a 引用,所以不會(huì)被回收
另外,delete o.x 也可以寫作 delete o["x"],兩者效果相同。
十一、其他不能被刪除的屬性
除了上面說(shuō)過(guò)的內(nèi)置屬性(即預(yù)定義屬性)不能被刪除外,prototype中聲明的屬性也不能delete:
function C() { this.x = 42; }
C.prototype.x = 12;
C.prototype.y = 13;
var o = new C();
o.x; // 42, 構(gòu)造函數(shù)中定義的o.x
delete o.x; //true 刪除的是自身定義的x
o.x; // 12, prototype中定義的o.x,即使再次執(zhí)行delete o.x也不會(huì)被刪除
delete o.y; //true,因?yàn)?o自身沒(méi)有o.y屬性,y存在于prototype鏈中,也就是說(shuō)對(duì)象自身屬性和prototype屬性是不同的
o.y; //13
小結(jié)
上面說(shuō)了那么多,希望對(duì)大家認(rèn)識(shí)JavaScript中的Delete有所幫助。由于水平有限,不保證完全正確,如果發(fā)現(xiàn)錯(cuò)誤歡迎指正。
原文為:
1、http://perfectionkills.com/understanding-delete/(英文)
2、http://nanto.asablo.jp/blog/2008/01/09/2552470(日文)
本文首發(fā)http://jscode.cnblogs.com
我們先來(lái)看看下面幾段代碼,要注意的是,以下代碼不要在瀏覽器的開發(fā)者工具(如FireBug、Chrome Developer tool)中運(yùn)行,原因后面會(huì)說(shuō)明:
為什么我們可以刪除對(duì)象的屬性:
復(fù)制代碼 代碼如下:
var o = { x: 1 };
delete o.x; // true
o.x; // undefined
但不以刪除像這樣聲明的變量:
復(fù)制代碼 代碼如下:
var x = 1;
delete x; // false
x; // 1
也不能刪除像這樣定義的函數(shù):
復(fù)制代碼 代碼如下:
function x(){}
delete x; // false
typeof x; // "function"
注意:當(dāng)delete操作符返回true時(shí)表示可以刪除,返回false表示不能刪除
要理解這一點(diǎn),我們首先需要掌握像變量實(shí)例化和屬性特性這樣的概念--遺憾的是這些內(nèi)容在一些javascript的書中很少講到。理解它們并不難,如果你不在乎它們?yōu)槭裁催@么運(yùn)行,你可以隨意的跳過(guò)這一部分。
二、代碼類型
在ECMAScript中有三種類型的可執(zhí)行代碼:Global code(全局代碼)、Function code(函數(shù)代碼)和 Eval code(放在Eval中執(zhí)行的代碼)。
復(fù)制代碼 代碼如下:
var x=1;//Global code
function test(){
var y=2;//Function Code
eval("var z=3");//Eval Code in Function
}
eval("function evalTest(){}");//Eval Code in Global
三、執(zhí)行上下文
當(dāng)ECMAScript 代碼執(zhí)行時(shí),它總是在一定的上下文中運(yùn)行,執(zhí)行上下文是一個(gè)有點(diǎn)抽象的實(shí)體,它有助于我們理解作用域和變量實(shí)例化如何工作的。對(duì)于三種類型的可執(zhí)行代碼,每個(gè)都有執(zhí)行的上下文。當(dāng)一個(gè)函數(shù)執(zhí)行時(shí),可以說(shuō)控制進(jìn)入到函數(shù)代碼(Function code)的執(zhí)行上下文。全局代碼執(zhí)行時(shí),進(jìn)入到全局代碼(Global code)的執(zhí)行上下文。
正如你所見,執(zhí)行上下文邏輯上來(lái)自一個(gè)棧。首先可能是有自己作用域的全局代碼,代碼中可能調(diào)用一個(gè)函數(shù),它有自己的作用域,函數(shù)可以調(diào)用另外一個(gè)函數(shù),等等。即使函數(shù)遞歸地調(diào)用它自身,每一次調(diào)用都進(jìn)入一個(gè)新的執(zhí)行上下文。
四、Activation object(激活對(duì)象)/Variable object(變量對(duì)象)
每一個(gè)執(zhí)行上下文在其內(nèi)部都有一個(gè)Variable Object。與執(zhí)行上下文類似,Variable object是一個(gè)抽象的實(shí)體,用來(lái)描述變量實(shí)例化的機(jī)制。有趣的是在代碼中聲明的變量和函數(shù)實(shí)際上被當(dāng)作這個(gè)變量對(duì)象的屬性被添加。
當(dāng)進(jìn)入全局代碼的執(zhí)行上下文時(shí),一個(gè)全局對(duì)象用作變量對(duì)象。這也正是為什么在全局范圍中聲明的變量或者函數(shù)變成了全局對(duì)象的屬性。
復(fù)制代碼 代碼如下:
/* remember that `this` refers to global object when in global scope */
var GLOBAL_OBJECT = this;
var foo = 1;
GLOBAL_OBJECT.foo; // 1
foo === GLOBAL_OBJECT.foo; // true
function bar(){}
typeof GLOBAL_OBJECT.bar; // "function"
GLOBAL_OBJECT.bar === bar; // true
全局變量變成了全局對(duì)象的屬性,但是,那些在函數(shù)代碼(Function code)中定義的局部變量又會(huì)如何呢?行為其實(shí)很相似:它成了變量對(duì)象的屬性。唯一的差別在于在函數(shù)代碼(Function code)中,變量對(duì)象不是全局對(duì)象,而是所謂的激活對(duì)象(Activation object)。每次函數(shù)代碼(Function code)進(jìn)入執(zhí)行作用域時(shí),就會(huì)創(chuàng)建一個(gè)激活對(duì)象(Activation object)。
不僅函數(shù)代碼(Function code)中的變量和函數(shù)成為激活對(duì)象的屬性,而且函數(shù)的每一個(gè)參數(shù)(與形參相對(duì)應(yīng)的名稱)和一個(gè)特定Arguments 對(duì)象也是。注意,激活對(duì)象是一種內(nèi)部機(jī)制,不會(huì)被程序代碼真正訪問(wèn)到。
復(fù)制代碼 代碼如下:
(function(foo){
var bar = 2;
function baz(){}
/*
In abstract terms,
Special `arguments` object becomes a property of containing function's Activation object:
ACTIVATION_OBJECT.arguments; // Arguments object
...as well as argument `foo`:
ACTIVATION_OBJECT.foo; // 1
...as well as variable `bar`:
ACTIVATION_OBJECT.bar; // 2
...as well as function declared locally:
typeof ACTIVATION_OBJECT.baz; // "function"
*/
})(1);
最后,在Eval 代碼(Eval code)中聲明的變量作為正在調(diào)用的上下文的變量對(duì)象的屬性被創(chuàng)建。Eval 代碼(Eval code)只使用它正在被調(diào)用的哪個(gè)執(zhí)行上下文的變量對(duì)象。
復(fù)制代碼 代碼如下:
var GLOBAL_OBJECT = this;
/* `foo` is created as a property of calling context Variable object,
which in this case is a Global object */
eval('var foo = 1;');
GLOBAL_OBJECT.foo; // 1
(function(){
/* `bar` is created as a property of calling context Variable object,
which in this case is an Activation object of containing function */
eval('var bar = 1;');
/*
In abstract terms,
ACTIVATION_OBJECT.bar; // 1
*/
})();
五、屬性特性
現(xiàn)在變量會(huì)怎樣已經(jīng)很清楚(它們成為屬性),剩下唯一的需要理解的概念是屬性特性。每個(gè)屬性都有來(lái)自下列一組屬性中的零個(gè)或多個(gè)特性--ReadOnly, DontEnum, DontDelete 和Internal,你可以認(rèn)為它們是一個(gè)標(biāo)記,一個(gè)屬性可有可無(wú)的特性。為了今天討論的目的,我們只關(guān)心DontDelete 特性。
當(dāng)聲明的變量和函數(shù)成為一個(gè)變量對(duì)象的屬性時(shí)--要么是激活對(duì)象(Function code),要么是全局對(duì)象(Global code),這些創(chuàng)建的屬性帶有DontDelete 特性。但是,任何明確的(或隱含的)創(chuàng)建的屬性不具有DontDelete 特性。這就是我們?yōu)槭裁匆恍傩阅軇h除,一些不能。
復(fù)制代碼 代碼如下:
var GLOBAL_OBJECT = this;
/* `foo` is a property of a Global object.
It is created via variable declaration and so has DontDelete attribute.
This is why it can not be deleted. */
var foo = 1;
delete foo; // false
typeof foo; // "number"
/* `bar` is a property of a Global object.
It is created via function declaration and so has DontDelete attribute.
This is why it can not be deleted either. */
function bar(){}
delete bar; // false
typeof bar; // "function"
/* `baz` is also a property of a Global object.
However, it is created via property assignment and so has no DontDelete attribute.
This is why it can be deleted. */
GLOBAL_OBJECT.baz = 'blah';
delete GLOBAL_OBJECT.baz; // true
typeof GLOBAL_OBJECT.baz; // "undefined"
六、內(nèi)置屬性和DontDelete
一句話:屬性中一個(gè)獨(dú)特的特性(DontDelete)控制著這個(gè)屬性是否能被刪除。注意,對(duì)象的內(nèi)置屬性(即對(duì)象的預(yù)定義屬性)有DontDelete 特性,因此不能被刪除。特定的Arguments 變量(或者,正如我們現(xiàn)在了解的,激活對(duì)象的屬性),任何函數(shù)實(shí)例的length屬性也擁有DontDelete 特性。
復(fù)制代碼 代碼如下:
(function(){
/* can't delete `arguments`, since it has DontDelete */
delete arguments; // false
typeof arguments; // "object"
/* can't delete function's `length`; it also has DontDelete */
function f(){}
delete f.length; // false
typeof f.length; // "number"
})();
與函數(shù)參數(shù)相對(duì)應(yīng)的創(chuàng)建的屬性也有DontDelete 特性,因此也不能被刪除。
復(fù)制代碼 代碼如下:
(function(foo, bar){
delete foo; // false
foo; // 1
delete bar; // false
bar; // 'blah'
})(1, 'blah');
七、未聲明的賦值
簡(jiǎn)單地就是未聲明的賦值在一個(gè)全局對(duì)象上創(chuàng)建一個(gè)可刪除的屬性。
復(fù)制代碼 代碼如下:
var GLOBAL_OBJECT = this;
/* create global property via variable declaration; property has DontDelete */
var foo = 1;
/* create global property via undeclared assignment; property has no DontDelete */
bar = 2;//可理解為 window.bar=2; 根據(jù)上面的第五點(diǎn)是可以刪除的
delete foo; // false
typeof foo; // "number"
delete bar; // true
typeof bar; // "undefined"
請(qǐng)注意,DontDelete特性是在屬性創(chuàng)建的過(guò)程中確定的,后來(lái)的賦值不會(huì)修改現(xiàn)有屬性已經(jīng)存在的特性,理解這一點(diǎn)很重要。
復(fù)制代碼 代碼如下:
/* `foo` is created as a property with DontDelete */
function foo(){}
/* Later assignments do not modify attributes. DontDelete is still there! */
foo = 1;
delete foo; // false
typeof foo; // "number"
/* But assigning to a property that doesn't exist,
creates that property with empty attributes (and so without DontDelete) */
this.bar = 1;
delete bar; // true
typeof bar; // "undefined"
八、Eval code
在Eval中創(chuàng)建的變量或方法比較特別,沒(méi)有DontDelete特性,也就是說(shuō)可以刪除。
復(fù)制代碼 代碼如下:
eval("var x = 1;");
console.log(x); // 1
delete x;
console.log(typeof x); // undefined
eval("function test(){ var x=1; console.log(delete x);/* false */;return 1;}");
console.log(test()); // 1
delete test;
console.log(typeof test); // undefined
注意,這里說(shuō)的在Eval中創(chuàng)建的變量或方法不包括方法內(nèi)部的變量或方法,如上面代碼中的紅色部分,仍然跟之前講的一致:不能被刪除。
九、FireBug的困惑
我們看一段在FireBug中執(zhí)行的代碼結(jié)果:
復(fù)制代碼 代碼如下:
var x=1;
delete x;
console.log(typeof x);//undefined
function y(){
var z=1;
console.log(delete z);//false
}
y();
delete y;
console.log(typeof y);//undefined
這明明是違反上述規(guī)則的,但跟上面第八點(diǎn)對(duì)比后發(fā)現(xiàn),這正在代碼在eval中執(zhí)行的效果。雖然沒(méi)有證實(shí),但我猜測(cè)FireBug(Chrome Developer tool)中控制臺(tái)代碼是用eval執(zhí)行的。
所以,當(dāng)大家在測(cè)試JS代碼時(shí),如果涉及到當(dāng)前上下文環(huán)境時(shí)特別要注意。
十、delete操作符刪除的對(duì)象
C++中也有delete操作符,它刪除的是指針?biāo)赶虻膶?duì)象。例如:
復(fù)制代碼 代碼如下:
class Object {
public:
Object *x;
}
Object o;
o.x = new Object();
delete o.x; // 上一行new的Object對(duì)象將被釋放
但Javascript的delete與C++不同,它不會(huì)刪除o.x指向的對(duì)象,而是刪除o.x屬性本身。
復(fù)制代碼 代碼如下:
var o = {};
o.x = new Object();
delete o.x; // 上一行new的Object對(duì)象依然存在
o.x; // undefined,o的名為x的屬性被刪除了
在實(shí)際的Javascript中,delete o.x之后,Object對(duì)象會(huì)由于失去了引用而被垃圾回收, 所以delete o.x也就“相當(dāng)于”刪除了o.x所指向的對(duì)象,但這個(gè)動(dòng)作并不是ECMAScript標(biāo)準(zhǔn), 也就是說(shuō),即使某個(gè)實(shí)現(xiàn)完全不刪除Object對(duì)象,也不算是違反ECMAScript標(biāo)準(zhǔn)。
“刪除屬性而不是刪除對(duì)象”這一點(diǎn),可以通過(guò)以下的代碼來(lái)確認(rèn)。
復(fù)制代碼 代碼如下:
var o = {};
var a = { x: 10 };
o.a = a;
delete o.a; // o.a屬性被刪除
o.a; // undefined
a.x; // 10, 因?yàn)閧 x: 10 } 對(duì)象依然被 a 引用,所以不會(huì)被回收
另外,delete o.x 也可以寫作 delete o["x"],兩者效果相同。
十一、其他不能被刪除的屬性
除了上面說(shuō)過(guò)的內(nèi)置屬性(即預(yù)定義屬性)不能被刪除外,prototype中聲明的屬性也不能delete:
復(fù)制代碼 代碼如下:
function C() { this.x = 42; }
C.prototype.x = 12;
C.prototype.y = 13;
var o = new C();
o.x; // 42, 構(gòu)造函數(shù)中定義的o.x
delete o.x; //true 刪除的是自身定義的x
o.x; // 12, prototype中定義的o.x,即使再次執(zhí)行delete o.x也不會(huì)被刪除
delete o.y; //true,因?yàn)?o自身沒(méi)有o.y屬性,y存在于prototype鏈中,也就是說(shuō)對(duì)象自身屬性和prototype屬性是不同的
o.y; //13
小結(jié)
上面說(shuō)了那么多,希望對(duì)大家認(rèn)識(shí)JavaScript中的Delete有所幫助。由于水平有限,不保證完全正確,如果發(fā)現(xiàn)錯(cuò)誤歡迎指正。
原文為:
1、http://perfectionkills.com/understanding-delete/(英文)
2、http://nanto.asablo.jp/blog/2008/01/09/2552470(日文)
本文首發(fā)http://jscode.cnblogs.com
您可能感興趣的文章:
- JavaScript中詭異的delete操作符
- js delete 用法(刪除對(duì)象屬性及變量)
- javascript delete 使用示例代碼
- JavaScript delete 屬性的使用
- JavaScript從數(shù)組中刪除指定值元素的方法
- Javascript根據(jù)指定下標(biāo)或?qū)ο髣h除數(shù)組元素
- js 刪除數(shù)組的幾種方法小結(jié)
- js刪除數(shù)組元素、清空數(shù)組的簡(jiǎn)單方法(必看)
- js刪除Array數(shù)組中指定元素的兩種方法
- 基于JavaScript實(shí)現(xiàn)移除(刪除)數(shù)組中指定元素
- Javascript remove 自定義數(shù)組刪除方法
- javascript中刪除指定數(shù)組中指定的元素的代碼
- JavaScript使用delete刪除數(shù)組元素用法示例【數(shù)組長(zhǎng)度不變】
相關(guān)文章
JavaScript中使用Spread運(yùn)算符的八種方法總結(jié)
這篇文章主要給大家介紹了JavaScript中使用Spread運(yùn)算符的八種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用JavaScript具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
JavaScript實(shí)現(xiàn)簡(jiǎn)單打地鼠游戲
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)單打地鼠游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
JS中的函數(shù)與對(duì)象的創(chuàng)建方式
這篇文章主要介紹了JS中的函數(shù)與對(duì)象的創(chuàng)建方式,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05
js中的document.querySelector()方法舉例詳解
這篇文章主要給大家介紹了關(guān)于js中document.querySelector()方法的相關(guān)資料,document.querySelector是JavaScript中的一個(gè)內(nèi)置方法,用于通過(guò)CSS選擇器選擇文檔中的第一個(gè)匹配元素,需要的朋友可以參考下2024-01-01
uniapp使用uni-file-picker實(shí)現(xiàn)上傳功能
這篇文章主要介紹了uniapp使用uni-file-picker實(shí)現(xiàn)上傳功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-07-07
Bootstrap學(xué)習(xí)系列之使用 Bootstrap Typeahead 組件實(shí)現(xiàn)百度下拉效果
這篇文章主要介紹了Bootstrap學(xué)習(xí)系列之使用 Bootstrap Typeahead 組件實(shí)現(xiàn)百度下拉效果的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07
JavaScript高級(jí)程序設(shè)計(jì) 閱讀筆記(七) ECMAScript中的語(yǔ)句
ECMAScript中的語(yǔ)句,學(xué)習(xí)js的朋友可以參考下2012-02-02

