今天读到一篇特好的文章,解决了我一直以来对javascript中delete用法不清的疑惑。
------------------------------------------------------------------------------------------------
先看一个在Firebug控制台和实际运行环境中执行同一段代码的差别:
在Firebug中一次执行如下几句:
var sum = function(a, b) {return a + b;} var add = sum; delete sum; typeof sum;
得到的结果是这样的:
>>> var sum = function(a, b) {return a + b;} >>> var add = sum; >>> delete sum true >>> typeof sum; "undefined"
也就是说delete sum能执行成功。
接下来在实际运行环境中执行:
<script type="text/javascript" language="javascript"> var sum = function(a, b) {return a + b;} var add = sum; alert(delete sum); alert(typeof sum); </script>
第一次弹出的是flase,第二次弹出的是function.
看来Firebug不能完全模拟真实的JavaScript执行环境,所以以后使用Firebug控制台的时候要小心哦~
接下来看看delete到底能删除什么
1.删除对象的属性
var o = { x: 1 }; delete o.x; // true o.x; // undefined
2.删除变量
var x = 1; delete x; // false x; // 1
3.删除函数
function x(){} delete x; // false typeof x; // "function"
4.删除宿主对象下的变量
//在ie浏览器下 window.flower="monkey"; delete flower; //抛出异常 alert(flower); //在ff浏览器下 window.flower="monkey"; delete flower; //true alert(flower) //undefined
同样,下面这段代码在火狐和IE中也是有差别的:
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"
接下来回顾了下执行上下文和作用域的相关知识
例如在全局作用域定义的变量或者函数,其实就是全局对象的一个属性:
/* 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
而当执行上下文为函数的时候,除了变量、函数,函数的参数也是上下文对象的一个属性:
(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的上下文对象的一个属性:
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 */ })();
接下来,回到delete的讨论
对象的内置属性不可删除,例如:
(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" })();
同样, 函数的参数也是不可删除的:
(function(foo, bar){ delete foo; // false foo; // 1 delete bar; // false bar; // 'blah' })(1, 'blah');
上面讲到, 使用var定义的变量是不能用delete删除的,然而如果不使用var却能删除,这是因为,不使用var时,实际上是申明了上下文对象的一个属性
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; delete foo; // false typeof foo; // "number" delete bar; // true typeof bar; // "undefined"
回到最开始那个问题,为什么Firebug的执行结果跟真实环境的执行结果不一样。
先看两段代码:
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控制台中的代码可能事先被解析了,并且按照Eval Code来执行。
这样的话,就可以通过eval来删除使用var定义的变量了。
我们知道,在同一个作用域中,同时申明一个函数和变量,不管谁先谁后,得到的都是函数:
function x(){ } var x; typeof x; // "function"
那么是否可以利用eval来实现对变量和函数的删除呢?
仔细看下面的几段代码:
var x = 1; /* Can't delete, `x` has DontDelete */ eval('function x(){};'); alert(typeof x); // "function" delete x; // 火狐下执行不成功,IE执行成功 alert(typeof x); //火狐下为function,IE下为undefined
function x(){}; /* Can't delete, `x` has DontDelete */ eval('function x(){}'); alert(typeof x); // "function" delete x; // 火狐下执行不成功,IE执行成功 alert(typeof x); //火狐下为function,IE下为undefined
var x = 1; /* Can't delete, `x` has DontDelete */ eval('var x = 1;'); alert(typeof x); // "number" delete x; alert(typeof x); //number
eval('var x = 1'); /* Can't delete */ alert(typeof x); // number delete x; alert(typeof x); //undefined
function x(){}; eval('var x = 0;'); /*没有被函数的定义覆盖*/ alert(typeof x); // number delete x; alert(typeof x); //number
总结一下:delete是否其作用,与delete的对象是变量还是对象的属性没有关系,只与DontDelete有关。
1.Variables and function declarations are properties of either Activation or Global objects.
变量声明和函数声明是调用对象或全局对象的属性。
2.Properties have attributes, one of which — DontDelete — is responsible for whether a property can be deleted.
属性有很多特征,其中一个是DontDelete,它负责决定该属性能否被删除。
3.Variable and function declarations in Global and Function code always create properties with DontDelete.
全局代码块和函数代码块中的变量声明和函数声明总是能创建含有DontDelete的属性。
4.Function arguments are also properties of Activation object and are created with DontDelete.
函数参数也是调用对象的属性,并且在创建的时候含有DontDelete。
5.Variable and function declarations in Eval code always create properties without DontDelete.
Eval代码块中的变量声明和函数声明总是创建不含DontDelete的属性。
6.New properties are always created with empty attributes (and so without DontDelete).
新属性中总是不含任何特征的,因此没有DontDelete特征。
7.Host objects are allowed to react to deletion however they want.
宿主对象被允许无论何时均可对删除做出响应。
注意:delete仅在删除一个不能删除的成员时,才会返回false,其他情况都返回true,所以true并不标示删除成功。
------------------------------------------------------------------------------------------------
另外,再附一篇不错的相关文章的链接:http://www.cnblogs.com/windows7/archive/2010/03/28/1698387.html