牛得一逼的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);   // 抛出错误

 

posted @ 2018-03-21 10:54  linweiws  阅读(196)  评论(0编辑  收藏  举报