underscore中rest参数实现原理
核心函数: restArgs
方法
源码:
var restArgs = function(func, startIndex) {
// 如果没有传入startIndex,startIndex默认为func函数形参个数的最后一个,也就说最后一个形参默认为rest对象
startIndex = startIndex == null ? func.length - 1 : +startIndex;
return function() {
// 获取实际参数个数和startIndex大小之差与0的最大值
var length = Math.max(arguments.length - startIndex, 0),
// 构建长度为length的rest数组
rest = Array(length),
index = 0;
// 初始化startIndex之后的所有元素为rest数组元素
for (; index < length; index++) {
rest[index] = arguments[index + startIndex];
}
// call性能加速处理常用0, 1, 2三种情况,剩余情况apply处理
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);
}
// 如果startIndex超过2,则执行默认的方法:构建args数组,含有所有参数
var args = Array(startIndex + 1);
// 构建args数组,结构:[1, 3, 4, [2, 3, 5]]
for (index = 0; index < startIndex; index++) {
args[index] = arguments[index];
}
// args最后一个参数为rest对象
args[startIndex] = rest;
return func.apply(this, args);
};
};
实例:
_.restArgs(function(value, rest){
console.log(value, rest);
})(1, 2, 3);
// 1, [2, 3]
解析:
在源码中,_.restArgs = restArgs
,也就说直接调用的restArgs
方法。该方法目的就是通过分割传入函数的形式参数,达到动态可变参数的效果。
实例中:startIndex
没有传值,则默认为func.length - 1
;通过比较实Math.max(arguments.length - startIndex, 0)
来确定rest
数组长度。接下来循环生成rest数组元素,如果startIndex
的取值为0 || 1 || 2
的话,进行优化加速【优化原理】,否则调用默认执行。
调用默认执行:因为rest
对象总是最后一个,则args
数组长度为startIndex + 1
,初始化args
数组元素,最后一个位置留给rest
对象,返回执行结果。
总结一下:restArgs函数解决了动态参数分配问题,返回构建好的类似[1, 2, [3, 4, 5]]形式的数组方便其他函数使用