JS 原型模式
1. 简介
原型模式(Prototype pattern),用原型实例指向创建对象的类,使用于创建新的对象的类的共享原型的属性与方法。
2. 实现
对于原型模式,我们可以利用JavaScript特有的原型继承特性去创建对象的方式,也就是创建的一个对象作为另外一个对象的prototype
属性值。原型对象本身就是有效地利用了每个构造器创建的对象,例如,如果一个构造函数的原型包含了一个name属性(见后面的例子),那通过这个构造函数创建的对象都会有这个属性。
在现有的文献里查看原型模式的定义,没有针对JavaScript的,你可能发现很多讲解的都是关于类的,但是现实情况是基于原型继承的JavaScript完全避免了类(class)的概念。我们只是简单从现有的对象进行拷贝来创建对象。
真正的原型继承是作为最新版的ECMAScript5标准提出的,使用Object.create
方法来创建这样的对象,该方法创建指定的对象,其对象的prototype
有指定的对象(也就是该方法传进的第一个参数对象),也可以包含其他可选的指定属性。例如Object.create(prototype, optionalDescriptorObjects)
,下面的例子里也可以看到这个用法:
// 因为不是构造函数,所以不用大写
var someCar = {
drive: function () { },
name: '马自达 3'
};
// 使用Object.create创建一个新车x
var anotherCar = Object.create(someCar);
anotherCar.name = '丰田佳美';
Object.create
运行你直接从其它对象继承过来,使用该方法的第二个参数,你可以初始化额外的其它属性。例如:
var vehicle = {
getModel: function () {
console.log('车辆的模具是:' + this.model);
}
};
var car = Object.create(vehicle, {
'id': {
value: MY_GLOBAL.nextId(),
enumerable: true // 默认writable:false, configurable:false
},
'model': {
value: '福特',
enumerable: true
}
});
这里,可以在Object.create
的第二个参数里使用对象字面量传入要初始化的额外属性,其语法与Object.defineProperties
或Object.defineProperty
方法类似。它允许您设定属性的特性,例如enumerable
, writable
或 configurable
。
如果你希望自己去实现原型模式,而不直接使用Object.create
。你可以使用像下面这样的代码为上面的例子来实现:
var vehiclePrototype = {
init: function (carModel) {
this.model = carModel;
},
getModel: function () {
console.log('车辆模具是:' + this.model);
}
};
function vehicle(model) {
function F() { };
F.prototype = vehiclePrototype;
var f = new F();
f.init(model);
return f;
}
var car = vehicle('福特Escort');
car.getModel();
3. 总结
原型模式在JavaScript里的使用简直是无处不在,其它很多模式有很多也是基于prototype的,这里大家要注意的依然是浅拷贝和深拷贝的问题,免得出现引用问题。
原型模式适合在创建复杂对象时,对于那些需求一直在变化而导致对象结构不停地改变时,将那些比较稳定的属性与方法共用而提取的继承的实现。
本文是系列文章,可以相互参考印证,共同进步~
- JS 抽象工厂模式
- JS 工厂模式
- JS 建造者模式
- JS 原型模式
- JS 单例模式
- JS 回调模式
- JS 外观模式
- JS 适配器模式
- JS 利用高阶函数实现函数缓存(备忘模式)
- JS 状态模式
- JS 桥接模式
- JS 观察者模式
网上的帖子大多深浅不一,甚至有些前后矛盾,在下的文章都是学习过程中的总结,如果发现错误,欢迎留言指出~
- cf------(round)#1 C. Ancient Berland Circus(几何)
- MySQL配置TokuDB的简单总结
- cf------(round)#1 B. Spreadsheets(模拟)
- sysbench压测MyCAT的shell脚本
- qemu-kvm中vcpu虚拟化到底是咋整的?
- 【给 iOS 开发者】人工智能在 iOS 开发上的应用和机会
- 【Python】Selenium辅助海量基金数据获取
- Django ORM的简单总结
- GO语言标准库概览
- 关于自动化平台的动态菜单设计
- go语言网络编程之tcp
- 实现简单的http并发请求,支持:GET、POST、HEAD、PUT
- 【go语言】Goroutines 并发模式(一)
- 【go语言】Goroutines 并发模式(二)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- css Backgroud-clip (文字颜色渐变)
- 微信小程序 buton清除默认样式
- 正则replace 回调函数里接收的参数是什么?
- 微信小程序使用pako.js的踩坑笔记
- Koa - 初体验(写个接口)
- Koa - 中间件(理解中间件、实现一个验证token中间件)
- Koa - 使用koa-multer上传文件(上传限制、错误处理)
- 原生js 复制内容到剪切板
- Vue - watch高阶用法
- 小程序如何支持使用 async/await (构建npm版)
- require.context批量引入文件
- Node笔记 - process.cwd() 和 __dirname 的区别
- 小程序如何支持使用 async/await
- 小程序 - 如何自定义导航栏
- protobuf 语法 与 protocol-buffers 的使用