JS 原型(一)对象根据原型查找属性或赋值

1,812 阅读2分钟

这是我参与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';
  1. 如果对象自身有 foo 这个普通数据访问属性,则会直接修改 foo 属性的值
  2. 如果对象自身没有foo 属性,则会查找对象的原型链,如果查找完整条原型链也没有,则 foo 会被直接添加到 myObject
  3. 如果对象自身没有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

除了这两种情况之外的情况,会发生屏蔽,使用原型链最底层的新定义的属性。