这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战
hi 我是小十七_,新年快乐,今天是大年初二,之前整理了 JS 原型链相关的知识,整理出了几篇文章,在这里分享给大家。这一篇文章讲的是,对象根据原型查找属性或赋值的方式。
javascript 中创建对象的时候,对象会有一个 [[Prototype]] 的默认属性,表示对于其他对象的引用。几乎所有对象创建时 [[Prototype]] 都会被赋予一个非空的值。
引用对象的属性值
它的作用是,我们试图去引用对象的属性时,对于默认的 [[Get]] 操作,首先会查找对象本身是否有这个属性,如果没有查到,会查找对象的原型链上是否有这个属性,如果查找完整条原型链还没有的话,返回 undefined。
var obj = {
a: 2
}
var res = Object.create(obj);
console.log(res.a); // 2
执行
Object.create时会创建一个新对象,把新对象的 [[Prototype]] 关联到指定对象。 所有对象的 [[Prototype]] 最终指向Object.prototype。
给对象的属性赋值
给对象设置属性不仅仅是直接给属性赋值,还有一个其他的判断规则。
myObject.foo = 'bar';
- 如果对象自身有
foo这个普通数据访问属性,则会直接修改foo属性的值 - 如果对象自身没有
foo属性,则会查找对象的原型链,如果查找完整条原型链也没有,则foo会被直接添加到myObject - 如果对象自身没有
foo属性,原型链上有,那么就会有下面两种特殊情况:
第一种
var obj = {};
Object.defineProperties(obj, {
a: {
value: 2,
writable: false
}
});
var res = Object.create(obj);
res.a = 3;
console.log(res.a); // 2
原型链的同名属性,writable 为 false,无法屏蔽,严格模式下会报错。
第二种:
var obj = {};
Object.defineProperties(obj, {
a: {
get: function(){
return 2;
}
}
})
console.log(obj.a); // 2
var res = Object.create(obj);
res.a = 3;
console.log(res.a); // 2
原型链上的同名属性,重写了 getter 或者 setter,会按照 getter 和 setter 走。
如果这两种情况还希望屏蔽原型链上的同名属性,则不要用 = 赋值,用 Object.defineProperties
除了这两种情况之外的情况,会发生屏蔽,使用原型链最底层的新定义的属性。