// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
var timeout, result;
var later = function(context, args) {
timeout = null;
if (args) result = func.apply(context, args);
};
var debounced = restArgs(function(args) {
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(later, wait);
if (callNow) result = func.apply(this, args);
} else {
timeout = _.delay(later, wait, this, args);
}
return result;
});
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
};
return debounced;
};
// Returns the first function passed as an argument to the second,
// allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function.
_.wrap = function(func, wrapper) {
return _.partial(wrapper, func);
};
// Returns a negated version of the passed-in predicate.
_.negate = function(predicate) {
return function() {
return !predicate.apply(this, arguments);
};
};
// Returns a function that is the composition of a list of functions, each
// consuming the return value of the function that follows.
_.compose = function() {
var args = arguments;
var start = args.length - 1;
return function() {
var i = start;
var result = args[start].apply(this, arguments);
while (i--) result = args[i].call(this, result);
return result;
};
};
// Returns a function that will only be executed on and after the Nth call.
_.after = function(times, func) {
return function() {
if (--times < 1) {
return func.apply(this, arguments);
}
};
};
// Returns a function that will only be executed up to (but not including) the Nth call.
_.before = function(times, func) {
var memo;
return function() {
if (--times > 0) {
memo = func.apply(this, arguments);
}
if (times <= 1) func = null;
return memo;
};
};
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = _.partial(_.before, 2);
_.restArgs = restArgs;
_.debounce
_.debounce = function(func, wait, immediate) {
var timeout, result;
var later = function(context, args) {
timeout = null;
if (args) result = func.apply(context, args);
};
var debounced = restArgs(function(args) {
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(later, wait);
if (callNow) result = func.apply(this, args);
} else {
timeout = _.delay(later, wait, this, args);
}
return result;
});
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
};
return debounced;
};
debounce中依然保留了一个类似throttled的函数debounced,同样有later函数。
debounce触发机制非常有趣,每次触发的方式是不同的,比如如果我们设定了immediate为true,则第一次触发由debounce内部直接调用完成,之后则都交给setTimeout的later函数执行,一旦我们在间隔期间使用函数,则我们看到
if (timeout) clearTimeout(timeout);
就会把这个定时取消,然后由于
var callNow = !timeout; // true
if (callNow) result = func.apply(this, args); // 立即调用函数
此时的timeout依然是个定时器,所以必然,callNow变为false,也就不会触发存入的函数
然后
timeout = setTimeout(later, wait);
重新定时,在later函数中
timeout = null; // 调用后会使用一次
将timeout变为null,便于下一次使用直接调用函数
没设定immediate则延迟执行later
_.wrap
// Returns the first function passed as an argument to the second,
// allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function.
_.wrap = function(func, wrapper) {
return _.partial(wrapper, func); // 提前输入fund给wrapper并返回这个已经提前输入的wrapper
};
_.negate
// Returns a negated version of the passed-in predicate.
_.negate = function(predicate) {
return function() {
return !predicate.apply(this, arguments);
};
};
将断言的结果的反形式写入
_.compose
// Returns a function that is the composition of a list of functions, each
// consuming the return value of the function that follows.
_.compose = function() {
var args = arguments; // 全是函数的数组
var start = args.length - 1;
return function() {
var i = start;
var result = args[start].apply(this, arguments); // 最后一个函数
while (i--) result = args[i].call(this, result); //不断将值送入下一个函数中
return result;
};
};
以最后一个函数为基准开始
var a = _.compose(function (s) {
console.log(s + 1)
return s + 1
},function (s) {
console.log(s + 1)
return s + 1
},function (s) {
console.log(s + 1)
return s + 1
},function (s) {
console.log(s + 1)
return s + 1
},function (s) {
console.log(s + 1)
return s + 1
},function (s) {
console.log('end')
return s + 1
});
a(1)
//
end
3
4
5
6
7
_.before
// Returns a function that will only be executed up to (but not including) the Nth call.
_.before = function(times, func) {
var memo;
return function() {
if (--times > 0) {
memo = func.apply(this, arguments);
}
if (times <= 1) func = null; // 释放函数内存
return memo;
};
};
_.once
_.once = _.partial(_.before, 2);
提前将2放入before之中,即规定仅能调用一次
_.restArgs
_.restArgs = restArgs;
var restArgs = function(func, startIndex) {
startIndex = startIndex == null ? func.length - 1 : +startIndex;
return function() {
var length = Math.max(arguments.length - startIndex, 0),
rest = Array(length),
index = 0;
for (; index < length; index++) {
rest[index] = arguments[index + startIndex];
}
switch (startIndex) {
case 0: return func.call(this, rest);
case 1: return func.call(this, arguments[0], rest);
case 2: return func.call(this, arguments[0], arguments[1], rest);
}
var args = Array(startIndex + 1);
for (index = 0; index < startIndex; index++) {
args[index] = arguments[index];
}
args[startIndex] = rest;
return func.apply(this, args);
};
};
就是给一个函数制造rest params
没了