什么是原型模式
GOF 的定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
很明显原型模式属于对象创建模式,它的核心在于对象拷贝。利用已存在的对象作为原型,对其进行克隆,创建新对象的时间减少。
实现
先简单看一下原型模式在Java这种面向对象的强类型语言的具体实现
- 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-- 通过拷贝得到的对象
三者之间的关系
使用
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中我们不需要刻意去实现原型模式,日常用原型最多的是参数传递和全局注册