全系列目录
- JavaScript设计模式读书笔记(一)=> 创建型设计模式
- JavaScript设计模式读书笔记(二)=> 结构型设计模式
- JavaScript设计模式读书笔记(三)=> 行为型设计模式
- JavaScript设计模式读书笔记(四)=> 技巧型设计模式
- JavaScript设计模式读书笔记(五)=>架构型设计模式,MVC,MVP,MVVM
1. 节流模式
这个单独找了搞了篇文章
https://blog.csdn.net/c_kite/article/details/90446725
2. 惰性模式
减少每次代码执行时的重复性的分支判断,通过对象的重定义来屏蔽原对象中的分支判断。下面来个浏览器的事件绑定兼容问题例子:
const A = {};
A.on = function (dom, type, fn) {
if (dom.addEventListener) {
A.on = function (dom, type, fn) {
dom.addEventListener(type, fn, false);
}
} else if (dom.attachEvent) {
A.on = function (dom, type, fn) {
dom.attachEvent('on' + type, fn);
}
} else {
A.on = function (dom, type, fn) {
dom['on' + type] = fn;
}
}
A.on(dom, type, fn);
}
A.on(document.body, 'click', function() {
alert('111')
})
3. 参与者模式/函数柯里化
书中本节写的比较水,推荐阅读 张鑫旭JS中的柯里化(currying),本小节代码转载此链接
柯里化定义:
在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
https://baike.baidu.com/item/柯里化/10350525?fr=aladdin
简单来说就是所谓“柯里化”就是使函数理解并处理部分应用。
首先ES5中的bind
就是典型的柯里化,下面看个例子:
if (!function() {}.bind) {
Function.prototype.bind = function(context) {
var self = this
, args = Array.prototype.slice.call(arguments);
return function() {
return self.apply(context, args.slice(1));
}
};
}
3.1. 柯里化例子1 =》参数复用
- 官员取老婆
var currying = function(fn) {
// fn 指官员消化老婆的手段
var args = [].slice.call(arguments, 1);
// args 指的是那个合法老婆
return function() {
// 已经有的老婆和新搞定的老婆们合成一体,方便控制
var newArgs = args.concat([].slice.call(arguments));
// 这些老婆们用 fn 这个手段消化利用,完成韦小宝前辈的壮举并返回
return fn.apply(null, newArgs);
};
};
// 下为官员如何搞定7个老婆的测试
// 获得合法老婆
var getWife = currying(function() {
var allWife = [].slice.call(arguments);
// allwife 就是所有的老婆的,包括暗渡陈仓进来的老婆
console.log(allWife.join(";"));
}, "合法老婆");
// 获得其他6个老婆
getWife("大老婆","小老婆","俏老婆","刁蛮老婆","乖老婆","送上门老婆");
// 换一批老婆
getWife("超越韦小宝的老婆");
- 小柯南,大柯南
var smallKenan = function(action) {
var bigKenan = function(doing) {
var result = "";
if (action === "take drugs") {
if (doing === "bathWithGirlFriend") {
result = "尖叫,新一,你这个色狼,然后一巴掌,脸煮熟了~";
} else if (doing === "pointOutKiller") {
result = "新一,这个案子就交给你的,快点找出谁是凶手吧~";
}
} else {
if (doing === "bathWithGirlFriend") {
result = "来吧,柯南,一起洗澡吧~";
} else if (doing === "pointOutKiller") {
result = "小孩子家,滚一边去!";
}
}
console.log(result);
return arguments.callee; // 等同于return bigKenan
};
return bigKenan;
};
// 小柯南吃药了,然后和毛利兰洗澡,凶案现场指证犯人;结果是……
smallKenan("take drugs")("bathWithGirlFriend")("pointOutKiller");
3.2. 柯里化例子2 =》 提前返回
上一小节惰性模式代码改一改就变成了柯里化,初始addEvent
的执行其实值实现了部分的应用(只有一次的if...else if...
判定),而剩余的参数应用都是其返回函数实现的,典型的柯里化。
看下面例子:
var addEvent = (function(){
if (window.addEventListener) {
return function(el, sType, fn, capture) {
el.addEventListener(sType, function(e) {
fn.call(el, e);
}, (capture));
};
} else if (window.attachEvent) {
return function(el, sType, fn, capture) {
el.attachEvent("on" + sType, function(e) {
fn.call(el, e);
});
};
}
})();
3.3. 柯里化例子3 =》延迟计算
例如累加计算某种物品的数量或者重量,看下面例子:
var curryWeight = function(fn) {
var _fishWeight = [];
return function() {
if (arguments.length === 0) {
return fn.apply(null, _fishWeight);
} else {
_fishWeight = _fishWeight.concat([].slice.call(arguments));
}
}
};
var fishWeight = 0;
var addWeight = curryWeight(function() {
var i=0; len = arguments.length;
for (i; i<len; i+=1) {
fishWeight += arguments[i];
}
});
addWeight(2.3);
addWeight(6.5);
addWeight(1.2);
addWeight(2.5);
addWeight(); // 这里才计算
console.log(fishWeight); // 12.5
虽然延迟计算听上去很高级,但是,恕我愚钝,我想破了脑袋也没想出哪种情况非要柯里化延迟计算实现才能显著提高性能。能想到的好处就是参数个数随意,比方说:
addWeight(2.3, 6.5);
addWeight(1.2, 2.5);
4. 等待者模式
等待者模式用来解决那些不确定先后完成的异步逻辑的。通过对多个异步进程监听,来触发未来发生的动作。其监听的异步逻辑完成时才会自动执行成功回调函数, 当然有一个异步逻辑执行失败了,它便会执行失败回调函数
看定义都知道这是ES6的Promise
,多个异步监听就是Promise.all()
参考资料:
张容铭著 javascript设计模式 182-252页