有如如下代码:

class Person {
  constructor(name) {
    this.name = name
  }
  hello() {
    console.log('hello')
  }
}

class Student extends Person {
  constructor(name, score) {
    super(name)
    this.score = score
  }

  introduce() {
    console.log(`我是${this.name},考了${this.score}分。`)
  }
}

const student = new Student('maple', 99)
console.log('student:', student)
student.introduce()
student.hello()

如上所示代码,运行结果如下:

student: Student {name: "maple", score: 99}
我是maple,考了99分。
hello

从第22行代码打印结果可以看出来,student 对象并没有打印出 introduce() 方法,但是第23行代码的结果可以看出来是可以通过 student 对象调用的!

如果该代码是在浏览器控制台中运行,那么你会发现这个打印的结果是可以展开的,如下所示:

image-20210422161808205.png

展开之后,有个 __proto__ 属性(该属性每个对象都有),里面就可以找到 introduce() 方法。

我们把这个 __proto__ 属性叫做student 对象的隐式原型

当我们在一个对象中找一个属性或者方法时,在当前的对象上找不到,那么就会到它的隐式原型上去找。

这就是为什么student 对象没有 introduce() 方法依然可以调用的原因,因为它的隐式原型上有这个方法。

我们可以通过 student.__proto__ 的方式访问它

image-20210422161909409.png

我们知道,student 对象是类 Student 实例化后得到的。

通过 Student.prototype 可以访问类 Student 的原型。

我们把这个 prototype 属性叫做 Student 类的显式原型

image-20210422161952855.png

对象的隐式原型的值 等于 其对应构造函数的显式原型的值。

也就是 student.__proto__Student.prototype 是相等的。

image-20210422162014116.png

再说最后的结果,student.hello() 是成功执行出结果的。

首先,student 在自身找不到 hello() 方法,那么进一步到隐式原型 __proto__ 中查找,但是还是没找到。就这么停止了吗?不!刚说了对象的隐式原型的值 等于 其对应构造函数的显式原型的值。也就是 student.__proto__ 指向了 Student.prototype ,两者是相等的。

Student.prototype 也是一个对象,是对象,就有 __proto__ 属性,那么这里继续到Student.prototype 中的 __proto__ 中查找,最后在 Student.prototype__proto__ 中查找到了 hello() 方法,因此可以调用。

image-20210422163107948.png

总的来说,当一个属性或者方法在 student 对象中找不到,那么就会到 student 对象原型上去找,还找不到,就会到 student 对象原型的原型上继续找。

这种一层层通过 __proto__ 组成的链子一样的路径中查找的过程中,这条链子,就叫做原型链。

当然不是无限制的一直查找下去的,最多查找到对象的最顶层 Object 。在 Object.prototype 中找不到就到Object.prototype.__proto__ 中继续找,而此时它的隐式原型 __proto__ 值为 null 。

分类: JavaScript 标签: 暂无标签

评论

全部评论 4

  1. 芭比
    芭比
    Google Chrome Windows 10
    看不懂,路过
  2. 鸟叔
    鸟叔
    Google Chrome Windows 7
    尽管没看懂,还是赞一下
  3. Rivalsa
    Rivalsa
    Google Chrome Android
    现在最新版的Chrome已经没有__proto__了,换成了[[prototype]]了,但是还是能访问到__proto__属性,与类的prototype属性是一样的。
    1. 枫雨
      枫雨
      Google Chrome Windows 10
      @Rivalsa我也发现了,不过问题不大哈哈

目录