02月09, 2018

js对象的属性设置和屏蔽

给对象设置属性其实并不仅仅是添加一个新属性或者修改已有的属性值。
下面我们来看一下nObj.name = 'fy'; 这么一个操作,到底有几种情况:
1、nObj本身就有名为name的普通数据访问属性,那么nObj.name = 'fy'就会只修改该属性值,会屏蔽原型链上层的name属性(假设nObj上层原型链中也有name属性)。
2、name属性不存在nObj对象上,就比如下面有一个对象obj,nObj是obj的子对象:

let obj = {name: 'fuyu'};  
let nObj = Object.create(obj);
nObj // {}
nObj.name // fuyu

当开始操作nObj赋值新name时,nObj自己增加了一个属性name,值为fy,但是obj上的name属性值还是fuyu,并没有修改

nObj.name = 'fy';  
nObj.name // fy
obj.name // fuyu  

3、如果nObj上没有name属性,并在nObj的原型链上层存在名为name的普通数据访问属性,并且没有被标记为只读(writable:false),那么就会直接在nObj中添加一个名为name的新属性,它是屏蔽属性:

let obj = {};
Object.defineProperty(obj, 'name', {
    writable:true,
    configurable: true,
    value: 'fuyu',
    enumerable: true,
})
obj //{name: "fuyu"}
let nObj = Object.create(obj);
nObj // {}
nObj.name // fuyu
nObj.name = 'fy';
nObj // {name: "fy"}
obj // {name: "fuyu"}

4、如果nObj上没有name属性,并在nObj的原型链上层存在名为name的普通数据访问属性,并且被标记为只读(writable:true),那么无法修改已有属性或者在nObj上创建屏蔽属性。

let obj = {};
Object.defineProperty(obj, 'name', {
    writable:false,
    configurable: true,
    value: 'fuyu',
    enumerable: true,
})
obj //{name: "fuyu"}
let nObj = Object.create(obj);
nObj // {}
nObj.name = 'fy';
nObj // {}     nObj中并没有添加进去name属性

obj // {name: "fuyu"} obj中属性name的值也并没有被修改

ps:如果在严格模式下是会报错的。 如果在这种情况下需要修改nObj增加name属性,那就需要用Object.defineProperty()的方式来添加,如下:

Object.defineProperty(nObj, 'name', {
    wiritable:false,
    configurable: true,
    value: 'fy',
    enumerable: true,
})
nObj //{name: "fy"}
nObj.name // fy
obj //{name: "fuyu"}
obj.name // fuyu

4、如果nObj上没有name属性,但在原型链上层存在name,并且它是一个setter,那就一定会调用这个setter,name不会被添加到nObj,也不会重新定义这个setter:

let obj = {};
Object.defineProperty(obj, 'name', {
    configurable: true,
    setter: function(val){console.log('修改name属性'); this._a_ = val},
    getter: function(){return this._a_},
    enumerable: true,
})
obj.name // undefined
obj.name = 'fuyu' // 打印出  “修改name属性”
obj // {_a_: "fuyu"}name: "fuyu"_a_: "fuyu"get name: ƒ ()set name: ƒ (val)__proto__: Object
obj.name // fuyu
obj._a_ // fuyu
let nObj = Object.create(obj);
nObj // {}
nObj.name = 'fy'; // 打印出  “修改name属性”
obj // {_a_: "fuyu"}
nObj // {_a_: "fy"}name: "fy"_a_: "fy"__proto__: Object
nObj.hasOwnProperty('name'); // false

本文链接:http://blog.hiraetho.com/post/js-object-setting-prop.html

-- EOF --

Comments