原型 prototype 和 proto

  • 所有的引用类型,都有一个隐式原型 __proto__ 属性,并且指向它的 prototype 原型对象
  • 每个构造函数(包括普通函数)都有一个 prototype 原型对象
  • 隐式原型 __proto__ 属性值指向它的构造函数的显式原型 prototype 属性
  • prototype 原型对象里的 constructor 属性指向构造函数本身
  • 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么它会去它的隐式原型__proto__(也就是它的构造函数的显式原型 prototype)中寻找

image.png

实例对象的 __proto__ 指向构造函数的 prototype,从而实现继承

prototype 对象相当于特定类型所有实例对象都可以访问的公共容器

示例:

  1. function Person(nick, age){
  2. this.nick = nick;
  3. this.age = age;
  4. }
  5. Person.prototype.sayName = function(){
  6. console.log(this.nick);
  7. }
  8. var p1 = new Person('Byron', 20);
  9. var p2 = new Person('Casper', 25);
  10. p1.sayName() // Byron
  11. p2.sayName() // Casper
  12. p1.__proto__ === Person.prototype // true
  13. p2.__proto__ === Person.prototype // true
  14. p1.__proto__ === p2.__proto__ // true
  15. Person.prototype.constructor === Person // true

原型链

当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾

示例:

var arr = [1,2,3]

arr.valueOf()  //  [1, 2, 3]

按照之前的理论,如果自身没有该方法,我们应该去 Array.prototype 对象里去找,但是你会发现 arr.__proto__ 上也没有 valueOf 方法

下面是查询 valueof() 的流程图:

以下是关系图:

最后一个 null 意味着查找结束,设计上是为了避免死循环而设置的,Object 的隐式原型指向 null

arr.__proto__ === Array.prototype
true
Array.prototype.__proto__ === Object.prototype
true
arr.__proto__.__proto__ === Object.prototype
true

// 原型链的终点
Object.prototype.__proto__ === null; // true

参考文章