首先:
delete操作符通常用来删除对象的属性,而不是一般的变量和函数。
例子:
//对象
var o = { x: 1 };
delete o.x; // true
o.x; // undefined
//变量
var x = 1;
delete x; // false
x; // 1
//函数
function x(){}
delete x; // false
typeof x; // "function"
变量属性的标记
我 们已经知道声明变量时发生了什么(他们都变成了当前上下文对象的属性),接下来我们就要看一下属性究竟是怎么样一回事。每一个变量属性都可以有以下任意多 个属性: ReadOnly, DontEnum, DontDelete, Internal。你可以把这些当做标记,标明了变量属性可以持有的某种特性。这里我们最感兴趣的就是DontDelete标记。
在 声明变量或者函数时,他们都变成了当前上下文对象的属性–对于函数代码来说是活动对象,对于全局代码来说则是变量对象,而值得注意的是这些属性在创建时 都带有DontDelete标记,但是显式或者隐式的赋值语句所产生的属性并不会带有这个标记!这就是为什么有一些属性我们可以删除,但另一些却不可以:
内建对象与DontDelete
DontDelete就是一个特殊的标记,用来表明某一个属性能否被删除。需要注意的是一些内建的对象是自动持有这个标记的,从而不能被删除,比如函数内的arguments,以及函数的length属性。
但是注意:
在eval中声明的变量创建时都不会带有DontDelete标记!
eval('var foo = 1;');
foo; // 1
delete foo; // true
typeof foo; // "undefined"
在函数内部也是一样的:
(function(){
eval('var foo = 1;');
foo; // 1
delete foo; // true
typeof foo; // "undefined"
})();
Firebug的困扰
在Firebug中能被删除(但是google流浪器中不能):
>> var sum = function(a, b) {return a + b;}
>>> var add = sum;
>>> delete sum
true
>>> typeof sum;
"undefined"
在Firebug控制台中的代码最终将通过eval执行,而不是作为全局代码或函数代码。显然地,这样声明出来的变量都不会带DontDelete标记,所以才能被删除!(译者:也不能太信任Firebug啊。)