函数相关
bind
我们有时候需要限定函数中的this的指向
var fn = function(){return this.name;};
var me = {name:'dino'};
var fn2 = _.bind(fn,me);
var name = fn2();
// name = 'dino'
bind巧妙的利用了javascript中函数的闭包
// 原理间隙
var myBind = function(fn,self){
return function(){
fn.call(self);
}
};
- 这里只简单的解释了对this的绑定,其实bind函数还可以绑定形参
- es5中,有原生的bind
partial
函数柯理化(其实用bind就可以实现)
var subtract = function(a, b) { return b - a; };
sub5 = _.partial(subtract, 5);
sub5(20);
=> 15
// Using a placeholder
subFrom20 = _.partial(subtract, _, 20);
subFrom20(5);
=> 15
partial还是使用了javascript的闭包
// 原理解析
var myPartial = function(fn){
var argu = [].slice.call(arguments,1);
return function(){
var argu2 = argu.concat([].slice.call(arguments,0));
return fn.apply(null,argu2);
};
};
memoize
范例
var fibonacci = _.memoize(function(n) {
return n < 2 ? n: fibonacci(n - 1) + fibonacci(n - 2);
});
原理解析,如果是完全一样的参数,得到的结果应该一样,那我不应该重复计算一次(不要考虑随机函数)
// 兔子数列
// 1,1,2,3,5,8,...
// 除了第一个和第二个为1,其余数字为前两个数字之和
// 求第index个数字
var tuzi = function(index){
if(index == 0 || index == 1){
return 1;
}else{
return tuzi(index-2) + tuzi(index-1);
}
};
// 以上用递归的算法没有问题,但是当index太大的时候,就会很慢,因为里面有重复计算
var dict = {};
var tuzi2 = function(index){
if(dict[index] === undefined){
if(index == 0 || index == 1){
dict[index] = 1;
}else{
dict[index] = tuzi2(index-2) + tuzi2(index-1);
}
}
return dict[index];
};
// 尝试计算第40个数字
// tuzi(40); 用时1194.910ms,结果是165580141
// tuzi2(40); 用时0.335ms,结果是165580141
// 可以看到显著提高了速度
// 一万年的闭包技巧...
// hashFunc是求个哈希值,以用做dict中的key
var myMemoize = function(fn,hashFunc){
var dict = {};
return function(){
var rst = hashFunc.apply(null,arguments);
if(dict[rst] === undefined){
dict[rst] = fn.apply(null,arguments);
}
return dict[rst];
};
};
throttle和debounce
此处借用网友的论述,因为他讲完了,我无话可说了
想象每天上班大厦底下的电梯。把电梯完成一次运送,类比为一次函数的执行和响应。假设电梯有两种运行策略 throttle 和 debounce ,超时设定为15秒,不考虑容量限制。
- throttle 策略的电梯。保证如果电梯第一个人进来后,15秒后准时运送一次,不等待。如果没有人,则待机。
- debounce 策略的电梯。如果电梯里有人进来,等待15秒。如果又人进来,15秒等待重新计时,直到15秒超时,开始运送。
他们都是节流函数,防止函数被过多调用(请考虑mousemove这样的情况)