以下概念引用自MDN。

一、JavaScript是基于原型的。es6中的class关键字只是一个语法糖。

二、null没有原型。每一个实例对象都有一个私有属性(_proto_)指向其构造函数的原型对象(prototype)。该原型对象也有一个自己的原型对象(_proto_)。依次层层向上直到一个对象的原型对象为null。几乎所有的对象都是Object的实例。

三、当访问一个对象的属性时,它不仅仅在该对象上寻找这个属性,还好搜索这个对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或者达到原型末端(即找不到原型对象了)。

四、构造函数其实是一个普通的函数。使用new关键字来操作这个普通函数的时候,这个普通函数就成为了构造函数(构造方法)

五、使用字面量或者其他方式创建的对象其_proto_指向Object的原型(Object.prototype)。Object的原型的原型为null。

六、使用字面量或者其他方式创建的数组其_proto_指向Array的原型Array.prototype)。Array的原型的原型为Object

七、所有的函数的_proto_指向Function的原型Function.prototype)。Function的原型的原型为Object

八、在原型链上查找属性比较耗时,影响性能。要检查对象是否具有自己定义的属性,而不是其原型链上的某个属性。可以使用方法hasOwnProperty。Object.keys()也不会获取原型链上面的属性。

例子

  1. 例1

  function Person (name, sex) {

    this.name = name

    this.sex = sex

  }

  Person.prototype.role = '学生'

  let zhangsan = new Person('zhang san', 18)

  console.log(zhangsan.name)// zhang san

  console.log(zhangsan.sex)// 18

  console.log(zhangsan.role)// 学生(这个在该对象的原型上面找到了这个属性)

  console.log(zhangsan.like)// undefined(这个一直都没有找到)

  2. 例2

  let obj = {

    name: 'zhang san',

    getName: function () {

      return this.name

    }

  }

  let person = Object.create(obj)// person的值是{}

  console.log(person.hasOwnProperty('name'))// false

  console.log(person.__proto__.hasOwnProperty('name'))// true

  person.getName()// zhang san(person的构造函数的原型对象obj,其_proto_(或者Object.getPrototypeOf(person) )指向obj)

  person.name = 'li si'

  person.getName()// li si