手记

JS原型链简述

  function Person() {} // constructor
  let p = new Person() // instance
  Person.prototype === p.__proto__ // 指向原型对象
  (p.__proto__ | Person.prototype).constructor // 指向构造函数

每一个构造函数都有一个prototype原型对象,原型对象都包含一个指针通过constructor指向构造函数,而实例都包含一个指向原型对象的内部指针__proto__。

来看一个例子:

现在有两个构造函数PersonA和PersonB

我们这样做:

  function PersonA() {}
  function PersonB(name) {
    this.name = name;
  }
  PersonA.prototype = new PersonB('1m')
  console.log(new PersonA().name)

到这里发现我们给PersonB添加了一个属性name后,并将PersonB的实例赋值给PersonA的原型,这个时候访问PersonA实例的name属性,返回值正好是我们为PersonB设置的name值。

总结一下:

如果要使用实例化对象的某个属性,会首先在该对象内部寻找该属性,如果没有就去该对象的原型中查找,如果还找不到,就继续往上查找,一直找到Object,如果还没有就会报undefined,这就JS中介绍的原型链。
搜索轨迹:

new PersonA() → new PersonB() → new PersonB().prototype...→ Object.prototype

咱们再来看一个例子:

现在有两个构造函数PersonA和PersonB

    function PersonA() {
      this.father = true;
    };
    PersonA.prototype.getIsFather = function() {
      return this.father;
    };
    function PersonB() {
      this.father = false;
      // 如果这里删除属性father $1 将输出 true
    };
    // 继承
    PersonB.prototype = new PersonA();
$1  console.log(new PersonB().getIsFather()); // false

在这个例子中,我们通过原型链的关系让PersonB的原型对象继承了PersonA的getIsFather方法,此时PersonB和PersonA的实例将共享PersonA的所有方法。

总结一下:

new PersonB()先会看看自己有没有getIsFather方法,显然是没有的,怎么办呢,它还得去原型对象中找找,其实它的原型对象中也没有,可是呢,由于PersonA的实例化对象赋值给了PersonB的原型对象,所以,访问PersonB的原型对象相当与访问PersonA的实例化对象。

我是底部
如果这篇文章对你有帮助,那真是一件很棒的事,如果内容有什么问题或建议,欢迎在下方留言。😀 😀 😀

2人推荐
随时随地看视频
慕课网APP