1.惰性求值
惰性函数模式是一种将对函数或请求的处理延时到真正需要结果时进行的通用概念
函数作为运算符参与运算,具有非惰性求值的特性,会对整个程序造成负面影响(javascript也支持非惰性求值)
var a=2;
function f(x){
return x;
}
alert(f(a,a=a*a))//2,第二个参数虽然不用,但也被会计算了
alert(f(a))//4
function f(){}// -->f(function(){while(true);}())//虽然f()没有参数,但调用时还是会执行传递给它的参数表达式,该表达式死循环,导致系统奔溃
var t;
function f(){
t=t?t:new Date();
return t;
}
f();//使用全局t存储时间对象,在每次调用函数时候必须重新求值
var f=(function(){
var t;
return function f(){
t=t?t:new Date();
return t;
}
})()l
f();//仍然没有优化调用时的效率,因为每次调用f()依然需要求值
惰性求值,函数f()的调用都只会简单的返回t保留在其闭包内的值,这样执行起来非常高效
var f=function(){
var t=new Date();
f=function(){
return t;
}
return f();
}
f();
2、记忆:函数利用对象区记住先前操作的结果,从而避免无谓的运算,javascript的对象和数组实现这种优化非常方便
使用递归函数计算fibonacci数列,一个fibonacci数字是之前两个fibonacci数字之和,最前面两个数字是0和1
var fibonacci=function(n){
return n<2?n:fibonacci(n-1)+fibnacci(n-2);
}
for(var i=0;i<=10;i+=1){
document.writeln('<br>'+i+':'+fibonacci(i))
}
以上fibonacci函数被调用了453次,其中循环了11次,自身调用了442次
优化:使用一个临时数组保存结果,保存的结果可以隐藏在闭包中,当函数被调用时,先看是否已经知道存储结果,如知道,就立即返回结果
var fibnacci=(function(){
var memo=[0,1];
var fib=function(n){
var result=memo[n];
if(typeof result!=='number'){
result=fib(n-1)+fib(n-2);
memo[n]=result;
}
return result;
};
return fib
})();
for(var i=0;i<=10;i+=1){
document.writeln('<br>'+i+':'+fibonacci(i))
}
此时,fibonacci函数只被调用29次,其中循环了11次,自身调用了18次
再优化:把这种函数抽象化,构造带有记忆功能的函数
var memoizer=function(memo,formula){
var recur=function(n){
var result=memo[n];
if(typeof result!=='number'){
result=formula(recur,n);
memo[n]=result;
}
return result;
};
return recur;
}
3.套用:将函数与传递给它的参数相结合,产生一个新的函数
var add=fuction(n){
return function(m){
return n+m;
}
}
document.writeln(add(2)(3))
javascript扩展一个curry()方法,实现函数的套用应用
Function.prototype.method=function(name,func){
if(!this.prototype[name]){
this.prototype[name]=func;
return this;
}
}
Function.method('curry',funciton(){
var slice=Array.prototype.slice;
var args=slice.apply(arguments),that=this;
return function(){
return that.apply(null,args.concat(slice.apply(arguments)))
};
});
var add=fuction(){
var i,sum=0;
for(i=0;i<arguments.length;i+=1){
sum+=arguments[i]
}
return sum;
};
var add1=add.curry(2);
document.writeln(add1(3));
4.模块化
javascript使用函数和闭包可以构建模块,模块就是一个提供姐哦股却隐藏状态与实现的函数和对象,通过函数构建模块,可以完全摒弃全局变量的使用
5.柯里化;把接收多个参数的函数变成接收一个单一参数的函数,并且返回一个新函数,这个新函数能够接收元函数的参数
6.高阶函数:对函数的进一步抽象,至少满足下列条件之一:1接收函数作为输入 2输出一个函数
未完待续(待完善)。。。