js中的行为委托和无类编程
概述
《你不知道的JavaScript》中有这么一段话:不幸的是,将类和继承的设计模式思维带入Javascript的想法是你所做的最坏的事情,因为语法可能会让你迷惑不已,让你以为真的有类这样的东西存在,实际上原型机制与类的行为特性是完全相反的。
js的原型机制本质上是行为委托机制。行为委托认为对象之间是兄弟关系,互相委托,而不是父类和子类的关系。
面向类的编程
class Polygon {
constructor(height, width) {
this.name = 'Polygon';
this.height = height;
this.width = width;
}
}
class Rectangle extends Polygon {
constructor(height, width) {
super(height, width);
this.name = 'Rectangle';
}
}
class Square extends Rectangle {
constructor(length) {
super(length, length);
this.name = 'Square';
}
}
如上所示,是一个四边形——矩形——正方形的类关系图。看起来设计的很好,但是由于他们的层级关系,他们有这些缺陷:
- 每次都要写constructor,有时还要去写prototype。
- 如果矩形这个类要增加一个行为,但是这个行为在正方形中不需要怎么办?
- 如果要在矩形和正方形之间再增加一层,要怎么办?
用面向类的设计模式,如果遇到上面3个问题,处理起来会很麻烦,这就导致整个架构非常难扩展。原因是在设计整个类的架构的时候,我们已经规定好了每个类的行为以及层级结构,如果后续它们有变动,就会触及到架构问题,所以修改起来会很麻烦。
行为委托
怎么解决上述的问题1呢?方法是利用行为委托。
let polygon = {
init: function(width, height){
this.width = width;
this.height = height;
this.setName();
},
setName: function() {
this.name = 'polygon';
}
}
let rectangle = Object.create(polygon);
rectangle.setName = function() {
this.name = 'rectangle';
}
//初始化一个polygon
const a = Object.create(polygon);
a.init(2,3);
//初始化一个rectangle
const b = Object.create(rectangle);
b.init(3,4);
//初始化一个rectangle
const c = Object.create(rectangle);
c.init(4,5);
可以看到,利用Object.create方法,使rectangle的prototype委托了polygon对象,从而能够使用polygon对象的各种方法。这样做的优点是,整个过程非常简洁,我们不需要去探究prototype,也不需要去管constructor。
值得一提的是,我们可以通过Object.assign来扩充rectangle对象的方法,而不需要一条条去写rectangle的方法。实例如下:
Object.assign(rectangle, {
setName: function() {
this.name = 'polygon';
},
setWidth: function(width) {
this.width = width;
},
setHeight: function(height) {
this.height = height;
}
});
无类编程
为了解决问题2和3,我们打算降低层级,对所有的类进行“扁平化”管理,即是说,让Polygon作为最底层的类,然后所有的类都继承自它,这样我们就非常好扩展了。实例如下:
class Polygon {
constructor(height, width) {
this.name = 'Polygon';
this.height = height;
this.width = width;
}
}
class Rectangle extends Polygon {
constructor(height, width) {
super(height, width);
this.name = 'Rectangle';
}
}
const rectangleMixinPublic = {
rectanglePublic1: function(){
},
rectanglePublic2: function(){
}
}
const rectangleMixinPrivate = {
rectanglePrivate1: function(){
},
rectanglePrivate2: function(){
}
}
Object.assign(Rectangle.prototype, rectangleMixinPublic, rectangleMixinPrivate);
class Square extends Polygon {
constructor(length) {
super(length, length);
this.name = 'Square';
}
}
const squareMixinPublic = {
squarePublic1: function(){
},
squarePublic2: function(){
}
}
const squareMixinPrivate = {
squarePrivate1: function(){
},
squarePrivate2: function(){
}
}
Object.assign(Square.prototype,
rectangleMixinPublic,
rectangleMixinPrivate,
squareMixinPublic,
squareMixinPrivate);
从上面的代码可以看到,通过利用扁平化使类都继承于基类,然后利用Object.assign方法进行扩展prototype,使整个架构非常灵活。
其它
当然,我上面只是举了一个例子来说明这几种编程方式,它们的具体应用还有很多方面,比如行为委托还用于封装行为,无类继承还可以通过函数封装成函数式编程的形式。
js中的行为委托和无类编程的更多相关文章
- 怎么理解js中的事件委托
怎么理解js中的事件委托 时间 2015-01-15 00:59:59 SegmentFault 原文 http://segmentfault.com/blog/sunchengli/119000 ...
- js中var的有或无--重复声明和以后的声明
js中var的有或无--重复声明和以后的声明 使用var语句多次声明一个变量不仅是合法的,而且也不会造成任何错误. 如果重复使用的一个声明有一个初始值,那么它担当的不过是一个赋值语句的角色. 如果重复 ...
- js中的事件委托或是事件代理
JavaScript(jQuery)中的事件委托 https://www.cnblogs.com/zhoushengxiu/p/5703095.html js中的事件委托或是事件代理详解 https: ...
- JS中的事件委托(事件代理)
一步一步来说说事件委托(或者有的资料叫事件代理) js中事件冒泡我们知道,子元素身上的事件会冒泡到父元素身上. 事件代理就是,本来加在子元素身上的事件,加在了其父级身上. 那就产生了问题:父级那么多子 ...
- js中的事件委托(事件代理)详解
本文转载:https://www.cnblogs.com/liugang-vip/p/5616484.html#!comments js中的事件冒泡.事件委托是js 中一些需要注意的小知识点,这里结合 ...
- JS中的单例模式及单例模式原型类的实现
单例模式 单例模式的定义: 保证一个类只有一个实例,并提供一个访问它的全局访问点 通过一个简单的例子来了解单例模式的作用: class Div { constructor() { return doc ...
- js中的事件委托或是事件代理详解
起因: 1.这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的: 2.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它 ...
- js中的事件委托详解
概述: 那什么叫事件委托呢?它还有一个名字叫事件代理,JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件.那这是什么意思呢?网上的各位 ...
- [转] js中的事件委托或是事件代理详解
起因: 1.这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的: 2.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它 ...
随机推荐
- codeforces 1041A Heist
electronic a.电子的 heist v.抢劫 in ascending order 升序 indice n.标记 device n.装置设备 staff n.职员 in arbitrary ...
- C语音秋季学习总结
我对下个学期的期望就是明确自己的目标,能在下学期中学习更多的知识
- ntp时间同步参考
https://blog.csdn.net/kamereon/article/details/54344114
- Demo002 IDEA中Junit单元测试的使用(初级篇)
推荐JUnit视频教程:JUnit-Java单元测试必备工具. 1.基本理论 1.1 单元测试 单元测试又称模块测试,属于白盒测试,是最小单位的测试.模块分为程序模块和功能模块.功能模块指实现了一个完 ...
- 【python原理解析】python中分片的实现原理及使用技巧
首先:说明什么是序列? 序列中的每一个元素都会被分配一个序号,即元素的位置,也称为索引:在python中的序列包含:字符串.列表和元组 然后是:什么是分片? 分片就是通过操作索引访问及获得序列的一个或 ...
- f5 主备模式切换
f5 主备模式 主机down自动切换到备 原主机重新启动,自动切换到原主机
- Socket 多线程编程
前面一片学习了TCP/IP的基础网络编程,并给出了简单的服务端与客户端通信交互的例子.还介绍了UPC的通信例子. 这次学习TCP/IP的多线程编程.因为涉及到TCP/IP一般都是多线程,服务端会一直监 ...
- android 隐藏虚拟按钮栏及标题等权限设置
华为手机有虚拟按钮,根据以下设置方法可以进行隐藏控制 /** * 隐藏虚拟按键,并且全屏 */ protected void hideBottomUIMenu(Context context){ if ...
- 15. pk-mext
在平时的生产环境中,我们经常会碰到监控MySQL的各个状态值的一个变化趋势,然后就会自己写个脚本,将status快照保存到文本中.当我们去分析的时候,需要自己去比较差值,是一件比较麻烦的时候,虽然可以 ...
- python07 函数式编程
1.作用域 1.1 pass关键字表示,暂时不写该方法 1.2表示返回值为方法 输出结果333 1.3函数作用域:和函数调用没关系,和声明的位置有关系, 结果为444 2.匿名函数 lanmbda ...