在了解属性设置和屏蔽之前我们理解一下ES5
中Object.create()这个方法
Object.create()
方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。
Object.create(...)是ES5中新增的函数,所以在ES5之前的环境中如果要支持这个功能的话就需要一段简单的polyfill代码。它部分实现了Object.create(...)的功能
if(!Object.create){
Object.create=function(o){
function F(){}
F.prototype=o;
return new Foo()
}
}
这段polyfill代码使用了一个一次性函数F,我们用过改写它的.prototype属性使其指向想要关联的对象,然后再使用new F()来构造一个新对象进行关联
1.什么是属性屏蔽
同一属性名即出现在对象中也出现在对象的[[Prototype]]链上层,那么就发生了屏蔽。
2.什么情况下会发生属性屏蔽
好了现在我们来看一段代码:
var obj={a:2}
var newObj=Object.create(obj)
console.log(newObj)
console.log(newObj.a)//2
我们打开控制台查看,发现控制台的打印了这样一段信息
现在我们在上述代码的基础上再加一段代码:
newObj.a=3
console.log(newObj)
观察控制台打印信息
于是我们就可以得出结论:
我们在给对象赋值时,如果在[[Prototype]]链上层存在你所赋值属性名,就会直接在该对象中添加一个相同属性名的新属性,它就是屏蔽属性。
事实是这样么:我们再来看一下下面这段代码:
var obj={}
Object.defineProperty(obj,'a',{
writable:false,
value:2
})
var newObj=Object.create(obj)
console.log(newObj)
console.log(newObj.a)//2
打印结果如下:
我们再来执行一下操作:
newObj.a=3
console.log(newObj)
此时我们再来看控制台的打印信息:
可以看到,对象中并没有创建屏蔽属性,那我们修改一下上面的结论
我们在给对象赋值时,如果在[[Prototype]]链上层存在你所赋值属性名并且没有被标记为只读(writable:false),那么就会直接在该对象中添加一个相同属性名的新属性,它就是屏蔽属性。
现在总该万无一失了吧,nonono,我们再来看下面一段代码:
var obj={
set a(val){
this._a_=val*2
}
}
obj.a=2
var newObj=Object.create(obj)
console.log(newObj)
我们再来看控制台的打印结果:
我们再来执行下赋值操作:
newObj.a=3
console.log(newObj)
我们再来观察一下控制台打印:
发现newObj并没有创建一个属性名为a的屏蔽属性,而是直接调用setter,所以上面的结论任然需要修改一下:
我们在给对象赋值时,如果在[[Prototype]]链上层存在你所赋值的普通名为普通数据访问属性并且没有被标记为只读(writable:false),那么就会直接在该对象中添加一个相同属性名的新属性,它就是屏蔽属性。
刚刚接触原型链,考虑可能不全,希望大神能帮我指出来