当前位置: 首页 > news >正文

[JS设计模式]Prototype Pattern

Prototype pattern

Prototype pattern可便于同类型的多个对象共享属性。原型(prototype)是JS原生的对象,其他对象可以通过原型链(prototype chain)来访问原型。单独看这句描述可能还是有点儿抽象,下面通过具体的示例来详细阐述。

class Dog {constructor(name) {this.name = name;}bark() {return `Woof!`;}
}const dog1 = new Dog("Kadi");
console.log(dog1.__proto__);
console.log(Dog.prototype);

这里可以看到,constructor有一个name属性;根据ES6类的语法规则,所有在类中定义的属性(本例的属性bark),都自动加入到类的prototype中,Dog类本身有两个属性:constructor和bark。

有两种方式可以查看类的原型中的属性,一种是通过类本身的prototype,另一种是通过实例的__proto__。

请添加图片描述

从上图的调试信息可以看到,Dog类的prototype也是一个object,其中有两个属性bark和constructor,另外还有一个原型对象([[Prototype]])。

请添加图片描述

通常类的实例的__proto__直接引用类的prototype,如果类本身不包含某个属性,JS就会向下搜索原型链,查看在原型链中是否能找到被访问的属性。而在dog1实例中,发现有两个[[prototype]],而且还有包含关系,这就是所谓的原型链。

因为所有实例都可以访问类的原型对象,因此原型模式使得实例在访问相同属性时,不用每次都创建该属性的副本。只需要将属性加入到原型中,则所有的实例都可以访问。另外,在创建实例对象后,也支持添加新的属性到原型中,其他实例对象也可以访问这个新加入的属性。

const dog2 = new Dog("Husky")
Dog.prototype.play = ()=> console.log(`playing`);
dog1.play();

我们再创建一个“Husky”的实例,然后对Dog类的原型添加一个新的属性play,接着通过dog1实例来调用play函数,看能否正常运行。

请添加图片描述
请添加图片描述

从运行结果来看,dog1能正常访问play属性。

再举个例子,定义一个SuperDog并继承Dog,SuperDog有一个fly属性。通过创建一个SuperDog的实例dog3,且dog3调用bark属性

class SuperDog extends Dog {constructor(name) {super(name);}fly() {console.log("Flying!");}
}const dog3 = new SuperDog("Super")
dog3.fly();
dog3.bark();
console.log(dog3.__proto__);

请添加图片描述

此示例中有3级原型链,实例访问属性的搜索路径也非常清晰。dog3._proto_ -> SuperDog.prototype -> Dog.prototype。

完整示例代码

class Dog {constructor(name) {this.name = name;}bark() {console.log("Woof!");}
}class SuperDog extends Dog {constructor(name) {super(name);}fly() {console.log("Flying!");}
}const dog1 = new Dog("Kadi");
console.log(dog1.__proto__);
console.log(Dog.prototype);const dog2 = new Dog("Husky")
Dog.prototype.play = ()=> console.log(`playing`);dog1.play();const dog3 = new SuperDog("Super")
dog3.fly();
dog3.bark();
console.log(dog3.__proto__);debugger

相关文章:

  • blob文件流前端显示pdf
  • GIT提交、回滚等基本操作记录
  • StackOverflowError的JVM处理方式
  • 10-2 HNCST - 多线程4 - 线程同步Condition——python
  • 2023年,我在美国的这一年!
  • CSS Grid 和 Flexbox
  • kivy开发一个登陆界面
  • 12.30_黑马数据结构与算法笔记Java
  • Java:IO流——字节流和字符流
  • Qlib从入门到精通
  • 2022年全国职业院校技能大赛高职组云计算正式赛卷第三场-公有云
  • pytorch01:概念、张量操作、线性回归与逻辑回归
  • 【论文阅读】Realtime multi-person 2d pose estimation using part affinity fields
  • x-cmd-pkg | 音视频处理领域中常用的开源转换工具:ffmpeg
  • Kubernetes 学习总结(43)—— Kubernetes 从提交 deployment 到 pod 运行的全过程
  • 【comparator, comparable】小总结
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • Android开源项目规范总结
  • Angular数据绑定机制
  • python3 使用 asyncio 代替线程
  • spring cloud gateway 源码解析(4)跨域问题处理
  • Vue 动态创建 component
  • 闭包--闭包作用之保存(一)
  • 不上全站https的网站你们就等着被恶心死吧
  • 可能是历史上最全的CC0版权可以免费商用的图片网站
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • 转载:[译] 内容加速黑科技趣谈
  • elasticsearch-head插件安装
  • 第二十章:异步和文件I/O.(二十三)
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​2021半年盘点,不想你错过的重磅新书
  • ​油烟净化器电源安全,保障健康餐饮生活
  • #100天计划# 2013年9月29日
  • #if 1...#endif
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (十六)Flask之蓝图
  • (原創) 博客園正式支援VHDL語法著色功能 (SOC) (VHDL)
  • (转)创业的注意事项
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .net mvc部分视图
  • .net 流——流的类型体系简单介绍
  • .NET 设计一套高性能的弱事件机制
  • .net/c# memcached 获取所有缓存键(keys)
  • .NET企业级应用架构设计系列之应用服务器
  • @autowired注解作用_Spring Boot进阶教程——注解大全(建议收藏!)
  • @media screen 针对不同移动设备
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具