JavaScript中所有的对象都有一个[[ prototype ]] 的内置属性,其实就是其他对象的引用。在你引用对象的属性时,会触发[[ GET ]]操作,会在当前的作用域里边寻找是否存在这个属性,如果没有就往上寻找。这个过程就是对象prototype的链式操作。
prototype的对象尽头就是Object.prototype
Object.prototype里边到底有什么:
一些常用的toString()、valueOf() 方法。
属性的设置与屏蔽
一个简单的赋值操作: obj.foo = 'bar';可能会发生以下三种可能。
1、在 prototype 链上存在 foo 属性,但是数据访问属性没有被标记为可读writable:false;
那么js就直接在你的obj中创建一个新的foo 的属性并赋值为 “bar”,这就是屏蔽属性。
2、如果在prototype 上面有foo,且被标记为writable: false,那么js无法修改已有属性或在obj上创建新的foo 。浏览器在严格模式下还会抛出一个错误,这条赋值会被忽略,不被执行最后。
3、如果在prototype上存在 foo 属性,而且他是一个setter,那就一定会调用这个setter,foo 不会被重新定义在obj中而且不会添加到obj。
这些情况会产生屏蔽:
myObj.val ++ 操作相当于myObj.val = myObj.val + 1,++ 操作会先从prototype上面查找val这个属性,然后从obj1上面找到了这个val并执行val = val+ 1;接着用[[ PUT ]]操作把赋值后的val赋给myObj。
总结:
如果要访问一个对象中并不存在的属性,[[GET]]操作就会自动查找内部prototype 关联的对象上面去找,一直到Object.prototype链上面去找。
所有的普通对象都有内置的prototype ,指向原型链的顶端,所以一些常用的toString()和valueOf()方法能在普通对象中使用。
关联两个对象常用的方法是new 关键字进行函数调用,使用new调用函数的时候会把新对象的prototype属性关联到其他对象,带new 的函数调用通常叫做“构造函数调用”,但是本质上和一些传统意义上的类构造函数是不一样的。