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.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它 ...
随机推荐
- ReactiveX 学习笔记(23)RxCpp
RxCpp RxCpp 是 ReactiveX 的 C++ 语言实现. 下载 RxCpp $ git clone --recursive https://github.com/ReactiveX/Rx ...
- linux下启动tomcat服务
Linux下tomcat服务的启动.关闭与错误跟踪,使用PuTTy远程连接到服务器以后,通常通过以下几种方式启动关闭tomcat服务:切换到tomcat主目录下的bin目录(cd usr/local ...
- 28.Hibernate-HQL查询.md
目录 1.概述 2.HQL实例 3.Criteria 查询 4.SQL本地查询 5.分页 1.概述 1)Get/load主键查询 2)对象导航查询 3)HQL查询, Hibernate Query l ...
- .do的消除
其实就是在web.xml中去掉.do即可 那里有拦截器作用,什么样的文件可以进入前端控制器1
- Html转成Image
html转图片,原来用了html2image.jar,但是做不到复杂的css js渲染效果. 在网友推荐下,可以用wkhtmltoimage插件,这是用谷歌浏览器的内核webkit,网上搜一下可以下载 ...
- 2018面向对象程序设计(Java)第17周学习指导及要求
2018面向对象程序设计(Java)第17周学习指导及要求(2018.12.20-2018.12.23) 学习目标 (1) 掌握线程同步的概念及实现技术: (2) Java线程综合编程练习 学习资 ...
- Linux下,如何查看磁盘是否包含数据
可以使用lquerypv -h来查看磁盘是否包含数据,或磁盘头是否被dd过.这在安装RAC的过程中,是非常实用的一个命令.如果不包括数据的话,那么如下所示: [ZFFR4CB2101:root]/]& ...
- mysql授权远程访问
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'IDENTIFIED BY '123456' WITH GRANT OPTION; Query O ...
- NodeJs第3方包说明
formidable 作用:实现简单文件上传 var formidable = require('formidable'); var form = new formidable.IncomingFor ...
- 图像处理项目——生成csv文件提高读取效率
利用pyhton脚本生成csv文件 *开发环境为windows PyCharm*使用的是pyhton脚本*生成人脸和人脸对应的标签的csv文件 一:主要步骤 1.载入对应路径2.提取每一张图片对应的位 ...