Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

细说JavaScript的delete运算符

  delete是一个运算符,返回值是一个布尔值,表示delete是否执行成功。delete的功能是从一个对象上删除一个键或者说删除一个属性。这个概念很简单,下面这个就是使用delete最简单的例子。 var o={a:1};
delete o.a;
alert(o.a); //undefined
  这个代码就是把o这个对象的a属性删除了。当执行delete时,它先寻找操作数地址所属的对象,然后从找到的对象中删除保存操作数地址的属性,并返回表示是否删除成功的布尔值。也许听着有点乱吧,我们把上面的代码稍微修改下再测试。 var o={a:[1,2,3]};
var e=o.a;
delete e;
alert(o.a); //1,2,3
  我们先不管delete有没有执行成功,但是o.a没有被删除是事实。注意我在上一段中对delete工作原理的描述,第一步是寻找“操作数地址所在的对象”,在这个代码中操作数是e,操作数的地址就是e这个变量本身的地址。要区别开变量本身的地址和变量指向的地址。不要以为o.a的值是一个数组,赋值给e之后e就是那个数组了。对象的赋值是地址传递没错,但是“赋值”这个操作就一定会经历至少一次内存的读写。把保存地址的变量看作一张纸,我们可以在上面写字。把o.a赋值给e就是把o.a上面的字抄到e上面。经过这个操作之后e上面记载的字就和o.a相同了,但这两张纸的本质并没有改变。而delete的第一个步骤是寻找操作地址所属的对象,这就好比那张纸的所有者。纸只是抄了一遍另一张纸的内容而已,所有者本身并不会改变。o.a的所有者是o、而e的所有者是window(全局变量是window的属性),这个概念不会因为赋值而改变。所以我们delete e;的时候找到的对象是window,并尝试从window中删除e这个属性。这说了一大堆,其实就是C语言中的二阶指针概念,如果之前有接触过一看就能看懂。
  那么,上面这个代码删除成功了吗?没有,因为直接用var声明的变量拥有禁止删除的性质。 var a=[1,2,3];
alert(delete a); //false
b=[1,2,3];
alert(delete b); //true
window.c=[1,2,3];
alert(delete c); //IE8-?错误:true
  直接删除var声明的变量就会失败,delete返回false。而不用var关键字声明的全局变量或者说window的属性是可以删除的,但是由于某些莫名其妙的安全限制,在IE8-中禁止删除显式定义在window对象上的属性。
  虽然delete是用来删除属性的,但是对象的属性未必都是哈希表,也有一些特殊的定义比如get和set关键字定义的属性。 var o={
  get a(){return 1},
  set a(e){this.b=e}
};
o.a="x"; //a是setter属性,这里实际上是给b属性赋值
delete o.a; //删除a,也就是同时删除了getter和setter
o.a="y"; //由于删除了a的setter,这里就直接给a赋值了
alert(o.a); //y
alert(o.b); //x
  这个代码就可以看出,getter和setter属性都是可以删除的。但是有一些对象自带的属性就无法删除,而有些却可以。 var a=[];
alert(delete a.length); //false
alert(delete Math.sqrts); //true
  具体到哪个属性可以删除貌似没有确切资料,我也懒的去逐个实验,但是我想没人会手贱到去删除自带属性吧。最后还有一种特殊情况,就是神奇的eval。 eval("var a=2");
alert(delete a); //true
  如果这个例子看不过瘾就看下面这个 (function(){
  var a;
  eval("var b");
  alert(delete a); //false
  alert(delete b); //true
})()
  在eval中使用var定义的变量是可以删除的。至于原因嘛,下面是我的猜测:我们都知道var和function语句会被预解析,也就是说当一个作用域开始执行前,引擎提前为这些变量分配了内存,他们保存在栈中,所以无法随意删除。而在代码中使用eval执行var语句的时候作用域已经执行了,作用域开始执行后栈的顶指针就已经改变了,这时当然无法添加或删除堆中的变量。于是引擎就只能在把eval动态声明的变量放入堆中,而堆没有栈的操作限制,随时都可以删除。这就是我理解的var变量无法删除和eval var变量可以删除的原因。我的猜测未必正确,只是觉得这样解释比较合理而已。如果觉得有异议可以提出一起探讨。
网名:
34.203.245.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^