参考:http://www.cnblogs.com/xboy2012/archive/2012/08/29/jsdelete.html
Javascript的变量
实际上Javascript中,变量 等同于 对象属性,这是因为 Javascript 在执行脚本之前会创建一个Global对象,所有的全局变量都是这个
Global对象的属性,执行函数时也会创建一个Activation对象,所有的局部变量都是这个Activation对象的属性。如下例:
var global = 42; this.global; // 42, 可以通过this来访问Global对象 this.global2 = 12; global2; // 12 function foo() { var local = 36; // 不过无法直接访问Activation, // 因此无法通过 foo.local 的方式来访问local变量 }
delete操作符删除的对象
C++中也有delete操作符,它删除的是指针所指向的对象 ,但Javascript的delete与C++不同,它不会删除指向的对象,而是删除属性本身
var o = {}; var a = { x: 10 }; o.a = a; delete o.a; // o.a属性被删除 o.a; // undefined a.x; // 10, 因为{ x: 10 } 对象依然被 a 引用,所以不会被回收
在实际的Javascript中,delete o.x之后,Object对象会由于失去了引用而被垃圾回收,所以delete o.x也就“相当于”删除了o.x所指
向的对象,但这个动作并不是ECMAScript标准,也就是说,即使某个实现完全不删除Object对象,也不算是违反ECMAScript标准。
隐式全局变量和明确定义的全局变量间有些小的差异,就是通过delete
操作符让变量未定义的能力。
- 通过var创建的全局变量(任何函数之外的程序中创建)是不能被删除的。
- 无var创建的隐式全局变量(无视是否在函数中创建)是能被删除的。
这表明,在技术上,隐式全局变量并不是真正的全局变量,但它们是全局对象的属性。属性是可以通过delete
操作符删除的,而变量是不能的:
// 定义三个全局变量 var global_var = 1; global_novar = 2; // 反面教材 (function () { global_fromfunc = 3; // 反面教材 }()); // 试图删除 console.log(delete global_var); // false console.log(delete global_novar); // true console.log(delete global_fromfunc); // true // 测试该删除 console.log(typeof global_var); // "number" console.log(typeof global_novar); // "undefined" console.log(typeof global_fromfunc); // "undefined"
但是有一点例外,就是通过 eval 执行的代码中,通过var声明的变量虽然与正常的var声明变量同属于Global对象,但它们不
具有DontDelete特性,能被删除。
eval("var x = 36;"); console.log(x); // 42 console.log(delete x); // false console.log(typeof x); // undefined
eval执行代码声明的变量到底是谁哪个对象的属性,和定义他时所在的作用域有关。而且eval和浏览器也有关,FF和IE下表现也不一致。
delete的返回值
delete是普通运算符,会返回true或false。规则为:当被delete的对象的属性存在并且拥有DontDelete时返回false,否则返
回true。这里的一个特点就是,对象属性不存在时也返回true,所以返回值并非完全等同于删除成功与否。
function C() { this.x = 42; } C.prototype.y = 12; var o = new C(); console.log(delete o.x); // true console.log(o.x); // undefined console.log("x" in o); // false // o.x存在并且没有DontDelete,返回true console.log(delete o.y); // true console.log(o.y); // 12 // o自身没有o.y属性,所以返回true // 从这里也可以看到prototype链的存在,对象自身属性和prototype属性是不同的 console.log(delete o.__proto__.y);//true console.log(o.y); //undefined console.log(delete o); // false // Global.o拥有DontDelete特性所以返回false console.log(delete undefinedProperty); // true // Global没有名为undefinedProperty的属性因此返回true console.log(delete 42); // true // 42不是属性所以返回true。有的实现会抛出异常(违反ECMAScript标准) var x = 24; console.log(delete x++); // true console.log(x); // 25 // 被删除的是x++的返回值(24),不是属性,所以返回true