目录

1.什么是原型模式

2 参与者

3 实例讲解

4 使用 Object.create实现原型模式

4.1 Object.create()的用法

4.2 用 Object.create实现继承

4.2.1 单继承

4.2.2 多继承

4.3 propertyObject参数

4.4 Polyfill

4.5 改写原型模式实现

5 总结


1.什么是原型模式

原型模式(prototype)是指用原型实例指向创建对象的种类,并且通过拷贝这些原型创建新的对象。 原型模式不单是一种设计模式,也被称为一种编程泛型。 从设计模式的角度讲,原型模式是用于创建对象的一种模式。我们不再关心对象的具体类型,而是找到一个对象,然后通过克隆来创建一个一模一样的对象。在其他语言很少使用原型模式,但是JavaScript作为原型语言,在构造新对象及其原型时会使用该模式。

2 参与者

原型模式的主要参与者有

客户端( Client) : 通过要求一个原型克隆自己来创建一个新的对象。

原型( Prototype) :创建一个接口来克隆自己

克隆( Clones ) :正在创建的克隆对象

3 实例讲解

在示例代码中,我们有一个CustomerPrototype对象,它可以克隆给定原型对象(Customer)。它的构造函数接受一个Customer类型的原型,然后调用克隆方法生成一个新的Customer对象,其对象属性值使用原型对象的值进行初始化。

这是原型模式的经典实现,但JavaScript可以使用其内置的原型更有效地实现这一功能,后边我们将会修改这一代码

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>JS原型模式:公众号AlbertYang</title></head><body></body><script>//客户原型类function CustomerPrototype(proto) {this.proto = proto;this.clone = function() {var customer = new Customer();customer.name = proto.name;customer.age = proto.age;return customer;};}//客户类function Customer(name, age) {this.name = name;this.age = age;this.say = function() {console.info("%c%s", "color:red;font-size:18px", "姓名: " + this.name + ", 年龄: " + this.age);};}function run() {var proto = new Customer("张三", 18);var prototype = new CustomerPrototype(proto);var customer = prototype.clone();customer.say();}run();</script>
</html>

4 使用 Object.create实现原型模式

在现有的文献里查看原型模式的定义,没有针对JavaScript的,你可能发现很多讲解的都是关于类的,但是现实情况是基于原型继承的JavaScript完全避免了类(class)的概念。我们只是简单从现有的对象进行拷贝来创建对象。

在新版的ECMAScript5标准中提出,使用Object.create方法来创建指定的对象,其对象的prototype有指定的对象(也就是该方法传进的第一个参数对象),也可以包含其他可选的指定属性。例如Object.create(prototype, optionalDescriptorObjects)。

4.1 Object.create()的用法

Object.create()方法用于创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。

语法:

Object.create(proto[, propertiesObject])

参数:

proto新创建对象的原型对象。

propertiesObject可选。如果没有指定为 undefined,则是要添加到新创建对象的不可枚举(默认)属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()的第二个参数。

返回值:一个新对象,带着指定的原型对象和属性。

4.2 用 Object.create实现继承

下面的例子演示了如何使用Object.create()来实现类式继承。这是所有JavaScript版本都支持的单继承。

4.2.1 单继承

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>JS原型模式:公众号AlbertYang</title></head><body></body><script>// 父类function Shape() {this.x = 0;this.y = 0;}// 父类的方法Shape.prototype.move = function(x, y) {this.x += x;this.y += y;console.info('Shape moved.');};// 子类function Rectangle() {Shape.call(this); // call方法用来调用父类Shape的构造函数}// 子类继承父类Rectangle.prototype = Object.create(Shape.prototype);//重新指定构造函数Rectangle.prototype.constructor = Rectangle;console.log(Rectangle);var rect = new Rectangle();console.log(rect);console.log('rect是Rectangle的实例吗?',rect instanceof Rectangle); // trueconsole.log('rect是Shape的实例吗?',rect instanceof Shape); // truerect.move(1, 1); // 输出, 'Shape moved.'</script>
</html>

4.2.2 多继承 

如果你希望能继承到多个对象,则可以使用混入的方式。

function MyClass() {SuperClass.call(this);OtherSuperClass.call(this);
}// 继承一个类
MyClass.prototype = Object.create(SuperClass.prototype);
// 混合其它类
Object.assign(MyClass.prototype, OtherSuperClass.prototype);
// 重新指定constructor
MyClass.prototype.constructor = MyClass;MyClass.prototype.myMethod = function() {// 。。。。。};

Object.assign 会把 OtherSuperClass原型上的函数拷贝到 MyClass原型上,使 MyClass 的所有实例都可以使用 OtherSuperClass 的方法。Object.assign 是在 ES2015 引入的,且可用 polyfilled。要支持旧浏览器的话,可用使用 jQuery.extend() 或者 _.assign()。

 4.3 propertyObject参数

<script>var o;// 创建一个原型为null的空对象o = Object.create(null);o = {};// 上面的一句就相当于:o = Object.create(Object.prototype);o = Object.create(Object.prototype, {// foo会成为所创建对象的数据属性foo: {writable: true,configurable: true,value: "hello"},// bar会成为所创建对象的访问器属性bar: {configurable: false,get: function() {return 10},set: function(value) {console.log("Setting `o.bar` to", value);}}});function Constructor() {}o = new Constructor();// 上面的一句就相当于:o = Object.create(Constructor.prototype);// 如果在Constructor函数中有一些初始化代码,Object.create不能执行那些代码// 创建一个以另一个空对象为原型,且拥有一个属性p的对象o = Object.create({}, {p: {value: 42}})// 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的:o.p = 24console.log(o.p) //42o.q = 12for (var prop in o) {console.log(prop); //q}delete o.p //false//创建一个可写的,可枚举的,可配置的属性po2 = Object.create({}, {p: {value: 42,writable: true,enumerable: true,configurable: true}});
</script>

4.4 Polyfill

Polyfill 是一块代码(通常是 Web 上的 JavaScript),用来为旧浏览器提供它没有原生支持的较新的功能。比如说 polyfill 可以让 IE7 使用 Silverlight 插件来模拟 HTML Canvas 元素的功能,或模拟 CSS 实现 rem 单位的支持,或或 text-shadow,或其他任何你想要的功能。

下边这个 polyfill 涵盖了Object.create主要的应用场景,它创建一个已经选择了原型的新对象,但没有把第二个参数考虑在内。尽管在 ES5 中 Object.create支持设置为[[Prototype]]为null,但因为JS以前一些老版本的限制,此 polyfill 无法支持该特性。

if (typeof Object.create !== "function") {Object.create = function (proto, propertiesObject) {if (typeof proto !== 'object' && typeof proto !== 'function') {throw new TypeError('Object prototype may only be an Object: ' + proto);} else if (proto === null) {throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument.");}if (typeof propertiesObject !== 'undefined') throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument.");function F() {}F.prototype = proto;return new F();};
}

4.5 改写原型模式实现

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>JS原型模式:公众号AlbertYang</title></head><body></body><script>// 因为不是构造函数(类),所以不用大写var customer = {name:'',age:'',say: function() {console.info("%c%s", "color:red;font-size:18px", "姓名: " + this.name + ", 年龄: " + this.age);}};function run() {// 使用Object.create创建一个新客户var myCustomer = Object.create(customer);myCustomer.name = '张三';myCustomer.age = '18';myCustomer.say();}run();</script>
</html>

5 总结

原型模式在JavaScript里的使用简直是无处不在,其它很多模式有很多也是基于prototype的,大家使用的时候要注意浅拷贝和深拷贝的问题,免得出现引用问题。

今天的学习就到这里,你可以使用今天学习的技巧来改善一下你曾经的代码,如果想继续提高,欢迎关注我,每天学习进步一点点,就是领先的开始。如果觉得本文对你有帮助的话,欢迎点赞,评论,转发!!!

设计模式(7)[JS版]-JavaScript设计模式之原型模式如何实现???相关推荐

  1. 设计模式(9)[JS版]-JavaScript设计模式之如何实现桥接模式???

    目录 1 什么是桥接模式 2 参与者 3 实例讲解 4 总结 1 什么是桥接模式 Bridge模式允许两个组件,即客户端和服务一起工作,每个组件都有自己的接口.Bridge是一种高级架构模式,它的主要 ...

  2. 设计模式(10)[JS版]-JavaScript如何实现组合模式???

    目录 1 什么是组合模式 2 主要参与者 3 代码实现 4 应用实例 4.1 表单验证 4.1 图片阅读器 5 总结 1 什么是组合模式 组合模式允许创建具有属性的对象,这些对象是原始项目或对象集合. ...

  3. 【设计模式_青春版】创建型|原型模式

    文章目录 原型模式(创建型) 原型模型的概念 一.实现Cloneable接口 二.实现自定义的顶层接口 java中的浅拷贝 Java中深拷贝 一.改造克隆方法 二.序列化与反序列化 总结 原型模式(创 ...

  4. 设计模式(6)[JS版]-JavaScript如何实现抽象工厂模式?

    目录 1 学习目标 2 什么是抽象工厂模式? 3 抽象工厂模式作用 4 工厂模式参与者 5 代码实现 1 学习目标 通过本篇文章的学习,你应当掌握以下知识: 1 知道什么是抽象工厂模式? 2 掌握抽象 ...

  5. JavaScript为什么使用原型模式而不是类模式

    导言: 作为JavaScript初学者的本菜鸡而言,刚一开始接触这门语言我就被他的原型模式给吓到了.并且在相当长的一段时间之内,我都完全不能理解或者不能接受这个模式.直到最近经过多方调查和思考才有所明 ...

  6. 23种设计模式C++源码与UML实现--原型模式

    原型模式 一个复杂对象,具有自我复制功能,统一一套接口. 原型模式主要面对的问题是:某些结构复杂的对象的创建工作,由于需求的变化,这些对象进场面对着剧烈的变化,但是他们却拥有比较一致的接口. 原型模式 ...

  7. JavaScript 面向对象 (prototype 原型模式)

    一. JavaScript 设计思想 1994年,网景公司(Netscape)发布了Navigator浏览器0.9版.这是历史上第一个比较成熟的网络浏览器,轰动一时.但是,这个版本的浏览器只能用来浏览 ...

  8. JavaScript --- [学习笔记] 原型模式

    说明 接JavaScript - > [学习笔记]观察者模式 & 理解对象 & 工厂模式 & 构造函数模式 上一篇构造函数模式创建的实例,不同实例的同一个方法是不相等的, ...

  9. 头像上传html js版,javascript头像上传代码实例

    上传头像: 相关关键词: ondragover(拖动元素在投放区内移动) ondrop (元素放在投放区触发但是要去处理浏览器默认事件的影响:ondragenter.ondragover) dataT ...

最新文章

  1. 第七篇:数据预处理(四) - 数据归约(PCA/EFA为例)
  2. 举行可衡量自动行驶车未来发展的“智能模型车竞赛大会” 2018
  3. Linux如何运行pipe1,Linux中的管道
  4. 如何发布一个npm包?
  5. 免费和开源世界里面有很多好的邮件服务器
  6. [转载]MIT牛人解说数学体系
  7. global.php,global.php
  8. 如何看待EMNLP2021 best paper? 邱锡鹏教授:以为走错会场了
  9. mysql 分组统计 取最大值_(Mysql)sql分组取最大值问题
  10. python里面if语句一直出错_python错误,写了个小程序,if语句总是不执行,求高手指点...
  11. LAMP架构调优(七)——Apache Prefork模式调优
  12. 在使用体验上,VS远远不如Eclipse
  13. 计算机组成原理学习-哈工大《计算机组成原理》第四章-上篇
  14. 双向循环链表的C++实现
  15. 编程求完全二叉树的叶子结点数
  16. 做独立app需要哪些东西?
  17. IT与商业管理的三大阶段
  18. 粉丝经历!湖大毕业工作2年,成功拿下字节跳动后端研发岗offer!
  19. 初识linux之管道
  20. 3Dmax调整模型参数的精度教程

热门文章

  1. 关于CNAS实验室认可你知道这些吗?
  2. 智能反射面中的恒模约束问题基于penalty convex-concave procedure (CCP)求解及matlab代码
  3. 问题解决:UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xcf in position 0: invalid continuation by
  4. 获得表空间增长量和增长率的脚本
  5. 工厂污染源工况监控系统
  6. cocos2dx 实现果冻,刀光等效果
  7. 街舞社区小程序 微信小程序毕业设计开发
  8. 2019 ICPC 上海 M Blood Pressure Game [血压游戏] 出题人原封不动标程
  9. 简单学习之MongoDB
  10. 滚动到界面,元素缓慢滑出(jquery / css)