【JavaScript】原型与原型链
原型
pototype
每个函数都有一个 prototype 属性,函数的 prototype 属性指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型 。
每一个 JavaScript 对象(null 除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性,如何关联呢?就是通过下面的 __proto__
。
proto
每一个JavaScript对象(除了 null )都具有的一个属性,叫 __proto__
,这个属性会指向该对象的原型。
绝大部分浏览器都支持这个非标准的方法访问原型,然而它并不存在于 Person.prototype 中,实际上,它是来自于 Object.prototype ,与其说是一个属性,不如说是一个 getter/setter,当使用 Object.__proto__
时,可以理解成返回了 Object.getPrototypeOf(obj) 。
Object.getPrototypeOf(p) === p.__proto__
constructor
那原型如何和构造函数关联呢?
每个原型都有一个 constructor 属性指向关联的构造函数。
Function.prototype.constructor === Function
实例与原型
当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。
但是万一还没有找到呢?原型的原型又是什么呢?
原型的原型
原型也是一个对象,既然是对象,我们就可以用最原始的方式创建它 ,其实原型对象就是通过 Object 构造函数生成的,结合之前所讲,实例的 __proto__
指向构造函数的 prototype。
原型链
上图中由相互关联的原型组成的链状结构就是原型链,也就是蓝色的这条线。
任何一个实例对象通过原型链可以找到它对应的原型对象,原型对象上面的实例和方法都是实例共享的。
一个对象中查找方法或属性时,它会先在自己的对象上去查找,如果找不到,就会沿着原型链__proto__ 一直
向上级原型查找。
注意:只有函数才有 prototype 属性,实例对象只有 __proto__
,而函数有 __proto__
是因为函数是 Function 的实例对象,但要区分函数的__proto__
和 prototype.prototype
(重要!!!)。
function a() {}
console.log(a.__proto__ === Function.prototype) // true
console.log(a.prototype.__proto__ === Function.prototype) // false
console.log(a.prototype.__proto__ === Object.prototype) // true