[[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对于对象属性进行操作,则不受影响。