JavaScript原型模式

49 阅读2分钟

什么是原型模式

GOF 的定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象

很明显原型模式属于对象创建模式,它的核心在于对象拷贝。利用已存在的对象作为原型,对其进行克隆,创建新对象的时间减少。

实现

先简单看一下原型模式在Java这种面向对象的强类型语言的具体实现 image.png

  • prototypt 声明一个克隆自身的接口
  • ConcretePrototype 实现一个克隆自身的操作
  • Client 克隆得到的新对象

在JavaScript中的原型

对象和类

js是动态的,并不提供类的实现,在es6中的关键字 class 也只是语法糖,实际上也是函数。js中只有对象(Object) 一种引用数据类型,创建一个对象使用的就是原型。

几乎所有JavaScript的对象都是位于原型链顶端的Object实例。

Object的原型是null null 没有原型

对象和类的创建方法

// 对象

let obj1 = {} // 通过字面量
let obj2 = new Object; // 构造函数


// 构造函数
function CreateObj1 (id){
    this.id=id;
}

new CreateObj1()

// 类
class CreateObj2 {
    constructor(id){
    this.id =id
    }
}
new CreateObj2(2);

原型链

原型在js中的三个元素

function CreateObj2(id){
    this.id = id
}

CreateObj2.prototype.show = function(){
    console.log(this.id);
    }
let obj2 = new CreateObj2()
  • 原型对象: {show:show(),constructor:CreateObj2(id)} 在这里使用 new CreateObj2() 创建的对象的原型中都有这个对象和属性
  • 构造函数: CreateObj2 使用这个函数来拷贝 原型对象
  • 实例对象: obj2-- 通过拷贝得到的对象

三者之间的关系

image.png 使用 class 实现上述例子

class CreateObj2 {
    constructor(id){
    this.id =id
    }
    show(){
    console.log(this.id);
    }
}

let obj2 = new CreateObj2(2);

限制忽略构造函数 关系就很简单了 实例对象.__proto__ == 原型对象 实际上是 obj2.__proto__ == CreateObj2.prototype

那原型对象既然是一个对象也会它自己的原型

obj2.__proto__.__proto__ //--> Object
obj2.__proto__.__proto__.__proto__ //--> null Object的原型是null

上述例子的原型链

obj2--> CreateObj2.prototype -- > Object.prototype -->null

继承

JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。

obj2.id //->2
obj2.show() //--> console.log(2)
  • id 是obj2 的属性,可以找到 得到2
  • show() 不是obj2的属性,是obj2__proto__的属性,也可以找到打印2 通过设置 class 或者 prototype 来实现继承

可以通过 Object.create()new 来实现继承

总结

JavaScript中的 对象都有一个 __proto__ 属性来访问原型对象,在使用对象的属性时会延着原型链一层一层往上找, 虽然会消耗性能但是很方便。

在js中我们不需要刻意去实现原型模式,日常用原型最多的是参数传递和全局注册