原型链的继承

168 阅读2分钟

[[prototype]]的那点事儿

对象有一个特殊的[[prototype]]属性,其实就是对象其他对象的引用。当我们试图引用对象的某个属性时,[[prototype]]就会排上用场。

当我们访问 obj.a的时候

  • 首先会检查对象的自身上是否有该属性,有的情况下会直接读取
  • 如果a属性不在obj对象身上,此时首先会在obj.__proto__上进行该属性的查找
  • 如果obj.__proto__上不具备该属性则会检查obj.proto.__proto__是否存在
  • 如果仍然没有则会继续找直到返回null

例如:

function doSomething(){}
doSomething.prototype.foo = "bar";
var doSomeInstancing = new doSomething();
doSomeInstancing.prop = "some value";
console.log("doSomeInstancing.prop:      " + doSomeInstancing.prop);
console.log("doSomeInstancing.foo:       " + doSomeInstancing.foo);
console.log("doSomething.prop:           " + doSomething.prop);
console.log("doSomething.foo:            " + doSomething.foo);
console.log("doSomething.prototype.prop: " + doSomething.prototype.prop);
console.log("doSomething.prototype.foo:  " + doSomething.prototype.foo);

则会输出以下内容

doSomeInstancing.prop:      some value
doSomeInstancing.foo:       bar
doSomething.prop:           undefined
doSomething.foo:            undefined
doSomething.prototype.prop: undefined
doSomething.prototype.foo:  bar

属性屏蔽

场景:当我们给某个对象的属性进行赋值操作

myObject.foo = "bar";
  • 首先,当myObject上包含相关属性的时候,且允许修改,该条赋值操作会直接替换原有属性

  • 如果属性同时存在myObject与上级[[prototype]]链上,该操作会触发属性屏蔽,对象的取值会始终优先最底层myObject上的属性。

  • 当foo属性不直接存在于myObject上,而是存在与上级原型链时

    1.当上级[[prototype]]链上存在该属性,且没有设置为只读,那么则会在myObject上直接创建foo属性。 2.当上级[[prototype]]链上存在该属性,并且被设置为只读,那么该操作无法为myObject创建屏蔽属性或者修改[[prototype]]上的值 3.在[[Prototype]] 链上层存在foo 并且它是一个setter,那就一定会调用这个setter。foo 不会被添加到(或者说屏蔽于)myObject,也不会重新定义foo 这个setter。

只读属性会阻止原型链下层创建同名属性,主要是为了保证上级属性在集成过程中的唯一性。该情况仅存在直接赋值的情况,对于Object.defineProoerty对于对象属性进行操作,则不受影响。