闭包
应闭包用
如果在一个大函数中有一些代码块能够独立出来, 我们常常把这些代码块封装在独立的小函数里面。独立出来的小函数有助于代码复用,如果这些 小函数有一个良好的命名,它们本身也起到了注释的作用。如果这些小函数不需要在程序的其他地方使用,最好是把它们用闭包封闭起来。
命令模式
把请求封装成对象,从而分离请求的发起者和请求的接收者之间的耦合关系。在命令执行前,在命令对象中植入命令的接收者。
将所有可执行的命令封装到一个对象中
var Dog={
bark:()=>{
console.log('汪')
},
eat:()=>{
console.log('咬')
}
}
然后抽象出一个控制器
var createCommand=function(receiver){
return {
bark:receiver.bark,
eat:receiver.eat,
}
}
for(var i=0,type;type=['a','b','c'][i++];){
(function(type){
Type['is'+type]=function(obj){
return Object.prototype.toString.call(obj)==='[object '+type+']'
})(type)
}
AOP
面向切面编程,抽象出一些和核心业务逻辑模块无关的功能。这些功能会以“动态织入”的方式掺入业务逻辑模块中。
如,可以通过增加原型方法来装饰一个现有的函数。
高阶函数的应用
柯里化
又称部分求值,利用闭包将求到的部分结果保存起来
var currying=function(fn){
var args=[]
return function(){
if(arguments.length==0){
return fn.apply(this,args)
}else{
[].push.apply(args,arguments)
return arguments.callee // es5后严格模式已禁用
}
}
}
去柯里化
提取出this,可以使一些原生的方法变成泛化的方法
Function.prototype.uncurrying=function(){
var self = this
return function(){
var obj=Array.prototype.shift.call(arguments) // 拿到泛化的this
return self.apply(obj, arguments)
}
}
节流函数
分批执行函数
相当于是手动异步,将一个可能会阻塞很长时间的程序分成几个异步来执行,当然前提是行为是重复性的。
var timeChunk=function(ary,fn,count){
var obj, t
var len=ary.length //所有数据
var start=function(){ // 执行函数,每次只处理一定长度的数据
for(var i=0;i<Math.min(count||1,ary.length);i++){
var obj=ary.shift() //每次取出一个数据
fn(obj) // 并执行
}
}
return function(){
t=setInterval(function(){
if(ary.length===0){ // 数据已被处理完
return clearInterval(t)
}
start()
},200)
}
}
惰性载入
一个相当神奇的写法,需要执行该逻辑的时候才会执行
// 该函数执行一次后,addEvent的指向才被确定
var addEvent = function (elem, type, handler) {
if (window.addEventListener) {
addEvent = function (elem, type, handler) {
elem.addEventListener(type, handler, false)
}
} else if (window.attachEvent) {
addEvent = function (elem, type, handler) {
elem.attachEvent(`on${ type}`, handler)
}
}
addEvent(elem, type, handler)
}