underscore中rest参数实现原理

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]]形式的数组方便其他函数使用

你可能感兴趣的:(underscore中rest参数实现原理)