原型及原型链

原型的根,即Object.prototype可以解释为共有属性对象。而对象中的__proto__是指向原型,则可以使用一些共有方法。

三大属性

prototype

  • 虽然在js中一切皆对象,函数也是对象

  • 但这里prototype构造函数(不是实例函数哦)特有的属性,这个属性也是对象

  • 这个对象就是调用构造函数而创建的实例的原型。后面会证明

  • 举例:

  • 1
    2
    3
    4
    5
    6
    function Person(){

    }
    var person = new Person()
    // Person.prototype就是函数Person的原型
    // 注意这里Person实际上是一个构造函数

_proto_

  • 上面可以看出构造函数Person new出了一个实例person

  • 那么实例personPerson.prototype是什么关系呢?

  • 1
    person.__proto__ = Person.prototype
  • 每个对象都有一个属性,就是__proto__,包括上面区分过的函数对象。

  • 该属性的含义就是指向对象的原型。

  • 所以实例对象的原型就是构造函数的原型

constructor

  • 我们一开始便称Person是构造函数,而英文constructor就是构造函数的意思,可想而知,总有什么点constructor指向Person

  • 1
    Person = Person.prototype.constructor
  • 上式也辅证了一点,prototype这个属性也是对象

实例与原型

  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    //1、查找某个属性的时候,先在实例中查找
    //2、在实例中查找不到,会在实例的原型中查找
    //3、在实例的原型中查找不到,就会到原型的原型中查找。
    // 注意:不会到兄弟实例中查找
    function Person(){
    }
    var person1 = new Person()
    var person2 = new Person()
    // Person.prototype.name = "Person"
    //person1.name = "person1"
    //person1.prototype.name = "person1" // 报错,实例对象无prototype这个属性
    //person2.name = "person2" // undefined 不会去兄弟子节点中去查找属性
    console.log(person1.__proto__ === Person.prototype)
    person1.__proto__.name = "person1" // 相当于添加到Person.prototype中,是属于构造函数,而不是实例
    console.log(person2.name) // 注释掉person2的赋值,会输出person1,证实上述
    console.log(Person.prototype.name) // person1
    console.log(person1.name)
  • 通过上述代码,可以验证的结论有:

    • 如果在person1实例中查找不到属性,即使在实例的原型也就是构造函数的原型中查找不到该属性,也不会再person2这个兄弟实例中去查找,会直接输出undefined
    • person1.__proto__.name = "person1"相当于Person.prototype.name = "person1"
    • 当然,如果Person.prototype.name不会往person1.name中去寻找

原型的原型

  • 上述提过:原型也是一个对象,那么原型就有创建它的构造函数。该函数就是Object
  • 上述又提过,__proto__在js中所有对象均存在。则Person.prototype.__proto__ = Object.prototype
  • 因为Object是构造函数,则符合上述关于prototype__proto__的关系。即Object.prototype.constructor = Object
  • 补充:Object是根节点的对象,再往上查找就是null:Object.prototype.__proto__ = null。其实也就意味着Object 的原型的原型是不存在的

原型链

综上所述,可以整理成一张图,此图来源于某神(懒得画了)

0

补充

  • 关于constructor属性:

  • 1
    2
    3
    4
    5
    function Person(){}
    var person = new Person()
    console.log(person.constructor === Person) // true
    // 其实person这个实例对象中是没有constructor这个属性的,但是其查找了Person.prototype,也就是按照属性的方式进行查找了
    // 也就是说person.constructor === Person.prototype.constructor

参考

https://juejin.im/post/5c4fdbae6fb9a049b07dc084