牛得一逼的delete操作符
我们知道delete操作符本身就是为了删除属性而量身定做的,但比较遗憾的是,如果属性是引用类型的话并不是删除属性的引用,仅仅只是断开属性和宿主对象的联系:
var a={ p:{ x:2 } }; var b=a.p; delete a.p; console.log(b); // 牛逼!引用并没有消失,输出{x:2}
另外,delete不可以删除configurable:false的属性(不可配置),况且,企图删除一个configurable:false的属性时delete会返回false,利用这个特性,我在想能不能以此判断一个属性可不可配置:
function isConfigurable(obj,name){ return delete obj[name]; } var o={ a:12 }; Object.defineProperty(o,'a',{ configurable:false }); console.log(isConfigurable(o,'a')); // false,不可配置
但这种做法的缺陷会带来“副作用”:如果是configurable:true则会把属性删除了,如果我们仅仅只是想判断是否可以配置则得不偿失了,还不如这样写:
var o={ a:2 }; function isConfigurable(obj,name){ return Object.getOwnPropertyDescriptor(obj,name).configurable; } console.log(isConfigurable(o,'a')); // true,可配置
而且,如果用delete来判断是否可以配置,我认为别人看你这段代码也不知道你想干啥。
需要注意的是,在全局里声明一个变量本身会把这个变量作为属性添加到全局对象(以下默认为浏览器里的window对象),但这个属性默认的configurable是false,所以delete对它无可奈何,但比较讽刺的是,在函数里的全局变量(也就是函数里无var声明的变量)也会作为属性添加到window对象对象,但这个属性默认的configurable是true,也就是说,可以用delete删除它:
var lala=4; console.log(Object.getOwnPropertyDescriptor(window,'lala').configurable); // false delete window.lala; // 删除 console.log(lala); // 4 console.log(window.hasOwnProperty('lala')); // true function foo(){ hehe=100; } foo(); console.log(Object.getOwnPropertyDescriptor(window,'hehe').configurable); // 牛逼!居然是true! delete window.hehe; console.log(window.hasOwnProperty('hehe')); // false,已经成功删除了! console.log(window.hehe); // undefined console.log(hehe); // 抛出错误