天天看点

你不知道的js -- 原型

JavaScript中所有的对象都有一个[[ prototype ]] 的内置属性,其实就是其他对象的引用。在你引用对象的属性时,会触发[[ GET ]]操作,会在当前的作用域里边寻找是否存在这个属性,如果没有就往上寻找。这个过程就是对象prototype的链式操作。

prototype的对象尽头就是Object.prototype 

Object.prototype里边到底有什么:

你不知道的js -- 原型

一些常用的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。

这些情况会产生屏蔽:

你不知道的js -- 原型
你不知道的js -- 原型

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 的函数调用通常叫做“构造函数调用”,但是本质上和一些传统意义上的类构造函数是不一样的。

继续阅读