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.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它 ...
随机推荐
- html迪士尼网页实现代码
html body> <div> <!-- 导航设置 --> <header> <nav ...
- 查看oracle的执行计划
基于ORACLE的应用系统很多性能问题,是由应用系统SQL性能低劣引起的,所以,SQL的性能优化很重要,分析与优化SQL的性能我们一般通过查看该SQL的执行计划,本文就如何看懂执行计划,以及如何通过分 ...
- OKHttp使用详解
一,OKHttp介绍 okhttp是一个第三方类库,用于android中请求网络. 这是一个开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献(该公司还贡献了Picasso和Leak ...
- 云笔记项目-笔记列表弹出"分享移动删除"子菜单
业务需求: 笔记列表里还有一个按钮可以弹出子菜单,要求做到以下几点: (1)点击选中的笔记行的弹出按钮后,弹出子菜单,再次点击,子菜单收回. (2)选中其他笔记后,子菜单消失.效果如下图所示: 业务分 ...
- EOS的发币逻辑
[EOS的发币逻辑] EOS官网的Guide中(参考[1]),描述了如何发自己的Token: 1.创建一个contract. 2.有一些create.transfer.close action. 3. ...
- CuratorBarrier
一.DistributedDoubleBarrier 同时开始,同时结束 package bjsxt.curator.barrier; import java.util.Random; import ...
- Python学习之MacBook Pro中PyCharm安装pip以及itchat
前言:Mac中自带的python没有用,自己安装了一个PyCharm,网上很多人说安装Itchat后会安装到自带的Python中去.本文记录怎么安装到自己安装的Python3.7中去.主要技术来源于h ...
- 556. Next Greater Element III下一个更大的数字
[抄题]: Given a positive 32-bit integer n, you need to find the smallest 32-bit integer which has exac ...
- 150. Evaluate Reverse Polish Notation逆波兰表达式
[抄题]: Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are ...
- angularjs1.x的directive中的link参数element见解
angular.module("APP",[]) .directive("testDw",function () { return{ restrict:&quo ...