[转]使用delete操作符删除window对象属性的问题

http://hi.baidu.com/jz1108/item/51e6aa3a0d6ae649033edcb5

使用delete操作符删除window对象属性的问题

        Javascript中的delete操作符可以用来删除对象的某个属性,但是当删除window对象的属性时,浏览器表现并不完全一致。

        window.obj = {value: 1};
        alert(enumObj(window.obj));
        try{
            delete window.obj;
        }
        catch(e){
            alert("error: " + e.message);
        }
        alert(enumObj(window.obj));

        function enumObj(o){
            if (!o) return;
            var s = "";
            for (p in o){
                s += p + ": " + o[p] + "\n";
            }
            return s;
        }

        以上代码首先为window对象添加了obj属性,使用enumObj可以查看obj的内容,接着使用delete删除这个属性,再查看属性内容。我们用Firefox跑一下这段代码,结果是:

       

       

        我们看到Firefox成功删除了window的obj属性。那么IE呢?

       

       

       

        IE比FF多弹出一次对话框,在try/catch中的删除代码执行出现了异常,最后的对话框验证了window的obj属性还是存在的。至于为什么会出 现异常现在还没有结论。另外经验证,Safari、Opera和Chrome的结果和Firefox一致。

        最近网上看到一篇文章,专门写delete操作符的,其中也提到了IE的这个bug。推荐阅读:http://perfectionkills.com/understanding-delete/

 

http://my.oschina.net/warmcafe/blog/75845

 

 

今天读到一篇特好的文章,解决了我一直以来对javascript中delete用法不清的疑惑。

------------------------------------------------------------------------------------------------

先看一个在Firebug控制台和实际运行环境中执行同一段代码的差别:

在Firebug中一次执行如下几句:

1 var sum = function (a, b) { return a + b;}
2 var add = sum;
3 delete sum;
4 typeof sum;

 

得到的结果是这样的:

1 >>> var sum = function (a, b) { return a + b;}
2 >>> var add = sum;
3 >>> delete sum
4 true
5 >>> typeof sum;
6 "undefined"

 

也就是说delete sum能执行成功。

接下来在实际运行环境中执行:

1 < script type = "text/javascript" language = "javascript" >
2    var sum = function(a, b) {return a + b;}
3    var add = sum;
4    alert(delete sum);
5    alert(typeof sum);
6 </ script >

 

第一次弹出的是flase,第二次弹出的是function.

看来Firebug不能完全模拟真实的JavaScript执行环境,所以以后使用Firebug控制台的时候要小心哦~

接下来看看delete到底能删除什么

1.删除对象的属性

1 var o = { x: 1 };
2 delete o.x; // true
3 o.x; // undefined

 

2.删除变量

1 var x = 1;
2 delete x; // false
3 x; // 1

 

3.删除函数

1 function x(){}
2 delete x; // false
3 typeof x; // "function"

 

4.删除宿主对象下的变量

1 //在ie浏览器下
2 window.flower= "monkey" ;
3 delete flower; //抛出异常
4 alert(flower);
5  
6 //在ff浏览器下
7 window.flower= "monkey" ;
8 delete flower; //true
9 alert(flower) //undefined

 

同样,下面这段代码在火狐和IE中也是有差别的:

01 var GLOBAL_OBJECT = this ;
02  
03 /*`foo` is a property of a Global object.
04    It is created via variable declaration and so has DontDelete attribute.
05    This is why it can not be deleted. */
06  
07 var foo = 1;
08 delete foo; // false
09 typeof foo; // "number"
10  
11 /*`bar` is a property of a Global object.
12    It is created via function declaration and so has DontDelete attribute.
13    This is why it can not be deleted either. */
14  
15 function bar(){}
16 delete bar; // false
17 typeof bar; // "function"
18  
19 /*`baz` is also a property of a Global object.
20    However, it is created via property assignment and so has no DontDelete attribute.
21    This is why it can be deleted. */
22 //-----下面这段有浏览器差异
23 GLOBAL_OBJECT.baz = 'blah' ;
24 delete GLOBAL_OBJECT.baz; // true
25 typeof GLOBAL_OBJECT.baz; // "undefined"

 

接下来回顾了下执行上下文和作用域的相关知识

例如在全局作用域定义的变量或者函数,其实就是全局对象的一个属性:

01 /* remember that `this` refers to global object when in global scope */
02 var GLOBAL_OBJECT = this ;
03  
04 var foo = 1;
05 GLOBAL_OBJECT.foo; // 1
06 foo === GLOBAL_OBJECT.foo; // true
07  
08 function bar(){}
09 typeof GLOBAL_OBJECT.bar; // "function"
10 GLOBAL_OBJECT.bar === bar; // true

 

而当执行上下文为函数的时候,除了变量、函数,函数的参数也是上下文对象的一个属性:

01 ( function (foo){
02  
03      var bar = 2;
04      function baz(){}
05  
06      /*
07      In abstract terms,
08  
09      Special `arguments` object becomes a property of containing function's Activation object:
10      ACTIVATION_OBJECT.arguments; // Arguments object
11  
12      ...as well as argument `foo`:
13      ACTIVATION_OBJECT.foo; // 1
14  
15      ...as well as variable `bar`:
16      ACTIVATION_OBJECT.bar; // 2
17  
18      ...as well as function declared locally:
19      typeof ACTIVATION_OBJECT.baz; // "function"
20      */
21  
22 })(1);

 

最后,eval中定义的变量是作为执行eval的上下文对象的一个属性:

01 var GLOBAL_OBJECT = this ;
02  
03 /* `foo` is created as a property of calling context Variable object,
04      which in this case is a Global object */
05  
06 eval( 'var foo = 1;' );
07 GLOBAL_OBJECT.foo; // 1
08  
09 ( function (){
10  
11      /* `bar` is created as a property of calling context Variable object,
12          which in this case is an Activation object of containing function */
13  
14      eval( 'var bar = 1;' );
15  
16      /*
17          In abstract terms,
18          ACTIVATION_OBJECT.bar; // 1
19      */
20  
21 })();

 

接下来,回到delete的讨论

对象的内置属性不可删除 ,例如:

01 ( function (){
02  
03      /* can't delete `arguments`, since it has DontDelete */
04  
05      delete arguments; // false
06      typeof arguments; // "object"
07  
08      /* can't delete function's `length`; it also has DontDelete */
09  
10      function f(){}
11      delete f.length; // false
12      typeof f.length; // "number"
13  
14 })();

 

同样, 函数的参数也是不可删除 的:

1 ( function (foo, bar){
2  
3      delete foo; // false
4      foo; // 1
5  
6      delete bar; // false
7      bar; // 'blah'
8  
9 })(1, 'blah' );

 

上面讲到, 使用var定义的变量是不能用delete删除的,然而如果不使用var却能删除 ,这是因为,不使用var时,实际上是申明了上下文对象的一个属性

01 var GLOBAL_OBJECT = this ;
02  
03 /* create global property via variable declaration; property has DontDelete */
04 var foo = 1;
05  
06 /* create global property via undeclared assignment; property has no DontDelete */
07 bar = 2;
08  
09 delete foo; // false
10 typeof foo; // "number"
11  
12 delete bar; // true
13 typeof bar; // "undefined"

 

回到最开始那个问题,为什么Firebug的执行结果跟真实环境的执行结果不一样。

先看两段代码:

1 eval( 'var foo = 1;' );
2 foo; // 1
3 delete foo; // true
4 typeof foo; // "undefined"

 

1 ( function (){
2  
3      eval( 'var foo = 1;' );
4      foo; // 1
5      delete foo; // true
6      typeof foo; // "undefined"
7  
8 })();

 

所以,在Firebug控制台中的代码可能事先被解析了,并且按照Eval Code来执行。

这样的话,就可以通过eval来删除使用var定义的变量了。

我们知道,在同一个作用域中,同时申明一个函数和变量,不管谁先谁后,得到的都是函数:

1 function x(){ }
2 var x;
3 typeof x; // "function"

 

那么是否可以利用eval来实现对变量和函数的删除呢?

仔细看下面的几段代码:

1 var x = 1;
2 /* Can't delete, `x` has DontDelete */
3       
4 eval( 'function x(){};' );
5  
6 alert( typeof x); // "function"
7 delete x; // 火狐下执行不成功,IE执行成功
8 alert( typeof x); //火狐下为function,IE下为undefined

 

1 function x(){};
2 /* Can't delete, `x` has DontDelete */
3       
4 eval( 'function x(){}' );
5  
6 alert( typeof x); // "function"
7 delete x; // 火狐下执行不成功,IE执行成功
8 alert( typeof x); //火狐下为function,IE下为undefined

 

1 var x = 1;
2 /* Can't delete, `x` has DontDelete */
3       
4 eval( 'var x = 1;' );
5  
6 alert( typeof x); // "number"
7 delete x;
8 alert( typeof x); //number

 

1 eval( 'var x = 1' );
2 /* Can't delete */
3 alert( typeof x); // number
4 delete x;
5 alert( typeof x); //undefined

 

1 function x(){};
2 eval( 'var x = 0;' );
3 /*没有被函数的定义覆盖*/
4 alert( typeof x); // number
5 delete x;
6 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并不标示删除成功。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值