来工厂车间里聊一聊 js 中的原型

515 阅读3分钟

我们以工厂生产产品为例来聊聊 js 中的原型

  • 首先,我们有一个构造函数 Product

    function Product(p){ this.p = p }

    它就相当于一个生产机器,能够产出各种产品(实例)

  • 我们可以通过

    let product = new Product(p)

    来创建一个实例,这个过程相当于生产了一件产品,这个实例就是产品

  • 机器(构造函数)生产产品,那必须有个模板样品,这个模板样品,就是这个构造函数的 prototype ,也就是原型对象,每一次实例化一个对象,都是根据构造函数的这个 prototype 为模板创建一个实例对象

  • 创建出来了实例对象 product ,在大部分浏览器里,它都会有一个对象 __proto__,这个对象就是 product 的构造函数的 prototype (生产这个 product 的机器所使用的模板样品)

  • 综上,我们可以知道构造函数有prototype 属性, 指向构造函数所使用的原型对象,而构造函数 new 出来的实例有 __proto__ 属性,指向这个实例的原型。实例的 原型__proto__ 同时也是构造函数所使用的原型对象 prototype

关于对象的原型和原型链

我们来看一个类

class SonClass{
    constructor( pro ){
        this.pro = pro
    }
    Intro(){
        console.log(" I am SonClass ")
    }
}
  • 实际上,类的本质是一个构造函数,或者说,类指向了一个构造函数,所以通过类去创建实例对象,本质仍然是通过构造函数去创建实例对象,此时,类的 prototype 属性,实际上就是构造函数的 prototype 属性,通过这个类 new 出来的实例对象的 __proto__ 等于这个类的 prototype
  • 值得注意的是,用一个类去构造一个实例时,这个实例的原型(也就是__proto__)不是这个类本身,而是这个类的原型对象(prototype

对象继承中的原型和原型链

class FatherClass{
    constructor(fatherpro){
        this.fatherpro = fatherpro
    }
    static function FatherFunc(){
        console.log("Here is a static function from FatherClass")
    }
}
class SonClass extends FatherClass{
    constructor(fatherPro,sonPro){
        super(fatherPro)
        this.sonPro = sonPro
    }
}

要了解对象继承中的原型和原型链,我们首先要了解,类实际上也是一个对象,其次,我们要知道,类继承的机制是什么,我们以一个例子来说明,SonClass 继承自 FatherClass的过程,相当于以下两行代码

Object.setPrototypeOf(SonClass.prototype, Father.prototype)
Object.setPrototypeOf(SonClass, FatherClass)
  • 我们先大致了解 Object.setPrototypeOf 方法,直白地讲,假设参数为两个对象(obj1,obj2),那该函数让 obj1.__proto__ = obj2,接着,我们分别来聊聊这两行代码
  • 第一行代码,我们把 SonClassFatherClass 两个类,看作两个构造函数(正如前文所说,类实际上是指向构造函数的),经过这一行代码,SonClass 的原型对象 prototype__proto__,等于了 FatherClass 的原型对象 prototype,所以SonClass.prototype.__proto__ === FatherClass.prototype的返回结果是 true
  • 第二行代码,我们把 SonClassFatherClass 两个类,看作两个对象(类实际上也是对象),经过这一行代码, SonClass 成功继承了 FatherClass 的静态属性,SonClass.__proto__ === FatherClass 的返回结果也是 true 最后,我们回到生产车间
  • 我们把 FatherClass 比作一台生产玩具汽车的机器,把 SonClass 比作一台生产超级玩具汽车的机器,它们都是类,也是构造函数,还是对象
  • SonClass 这台机器,是以 FatherClass 这台机器为样品去创建出来的(这时我们把两台机器都看作对象),那么显然有 SonClass.__proto__ === FatherClass 的结果为 true
  • 其次呢,SonClass 这台机器生产过程中所使用的样品,也是根据 FatherClass 这台机器生产过程中所使用的样品为样品去创建出来的(这时我们把两台机器看作构造函数),也就是说 FatherClass 的产品(FatherClass.prototype)是SonClass的产品样品的样品(SonClass.prototype.__proto__),也就是说超级玩具汽车样品是以超级汽车的样品作为样品去创造出来的,显然有 SonClass.prototype.__proto__ === FatherClass.prototype

以上是我对 js 中的原型与原型链的理解,如有错误之处,欢迎批评指正