Skip to content

刨析原型

本文将从什么是原型,原型是怎么由来的,原型链又是什么,原型与原型链之间的关系,以及和原型相关的一些api的概念解释

原型

原型从字面意思就可以知道是一个事物的根本面目,那么什么才算是事物根本面目

实例与构造函数

js
// 构造函数
function F() {}
// 实例
const f = new F()

通过这个js代码很容易知道实例就是事物,而构造函数则是实例的本来面目。这也是我们常说的new 一个对象,来创建一个实例。

相关的API

constructor

其实在类型判断的时候也有介绍过,使用constructor则可以知道是由构造器创造出来的(前提是没有故意修改掉这个属性)。

js
// 构造函数
function F() {}
// 实例
const f = new F()
console.log(f.constructor === F) // true
f.constructor = Object
console.log(f.constructor === F) // false

protoype

在很多时候,我们new出来的实例可能会重复使用统一功能的函数,这个时候我们可以把方法或者数据存在在原型上,实现共享的功能

js
F.prototype.sayHello = function () {
  console.log('Hello!')
}

proto

让实例能找到自己的原型对象

js
// 构造函数
function F() {}
// 实例
const f = new F()
console.log(f._proto_)

原型链

当原型或者实例不断的继承时,就会出现一条继承的线路,我们把这样的线路称为原型链

继承方法

  1. 原型链继承 利用prototype。通过下面的代码也可以知道当使用prototype继承的时候实例的constructor是使用的最顶层原型的构造器,因此我们也可以推断出这个constructor是和prototype同级别存放在构造器中的,然后constructor指向本身

    js
    function Parent() {
      this.name = 'parent'
      this.arr = [1, 2, 3]
    }
    
    Parent.prototype.getName = function () {
      return this.name
    }
    
    function Child() {}
    
    Child.prototype = new Parent()
    const child1 = new Child()
    const child2 = new Child()
    child1.arr.push(999)
    console.log('child1', child1, child1.arr) // child1 Parent {} [ 1, 2, 3, 999 ]
    console.log('child2', child2, child2.arr) // child2 Parent {} [ 1, 2, 3, 999 ]
    console.log(child1.constructor) // [Function: Parent]
  2. 构造函数继承

    js
    function Parent() {
      this.info = {
        name: 'yhd',
        age: 19,
      }
    }
    function Child() {
      Parent.call(this)
    }
    
    let child1 = new Child()
    child1.info.gender = '男'
    console.log(child1.info) // {name: "yhd", age: 19, gender: "男"};
    let child2 = new Child()
    console.log(child2.info) // {name: "yhd", age: 19}
  3. 组合继承(原型链 + 构造函数继承)

    js
    function Person(name, age) {
      this.name = name
      this.age = age
      this.friends = ['Yasuo', 'Zed', 'Yi']
    }
    Person.prototype.running = function () {
      console.log('在跑步~')
    }
    function Student(name, age) {
      Person.call(this, name, age)
      this.score = 99
    }
    Student.prototype = new Person()
    Student.prototype.goToSchool = function () {
      console.log('去上学~')
    }
    let s1 = new Student('Cyan', 18)
    let s2 = new Student('Csy', 22)
    console.log(s1.name)
    console.log(s2.name)
    s1.friends.push('LeeSin')
    console.log(s1.friends)
    console.log(s2.friends)
    console.log(s1.running())
  4. 寄生式组合继承 Object.create()

    js
    function Person(name, age) {
      this.name = name
      this.age = age
      this.friends = ['Yasuo', 'Zed', 'Yi']
    }
    Person.prototype.running = function () {
      console.log('在跑步~')
    }
    function Student(name, age) {
      Person.call(this, name, age)
      this.score = 99
    }
    Student.prototype = Object.create(Person.prototype)
    Student.prototype.goToSchool = function () {
      console.log('去上学~')
    }
    let s1 = new Student('Cyan', 18)
    let s2 = new Student('Csy', 22)
    console.log(s1.name)
    console.log(s2.name)
    s1.friends.push('LeeSin')
    console.log(s1.friends)
    console.log(s2.friends)
    console.log(s1.running())