不定參數(rest 參數 ...)

不定參數

如何實現不定參數

使用過 underscore.js 的人,確定都使用過如下幾個方法:javascript

_.without(array, *values) //返回一個刪除全部values值後的array副本
_.union(*arrays) //返回傳入的arrays(數組)並集
_.difference(array, *others)//返回來自array參數數組,而且不存在於other 數組
...

這些方法都有一個共同點,就是能夠傳入不定數量的參數,例如,我想刪除掉 array 中的 value1,value2 ,能夠這樣使用 , _.without(array,value1,value2);java

那麼,這個須要怎樣才能作到呢?

咱們知道,js 中 function 裏面,有一個 arguments 參數,它是一個類數組,裏面包含着調用這個方法的全部參數,因此能夠這樣處理:es6

_.without = function() {
    if (arguments.length > 0) {
        var array = arguments[0];
        var values = [];
        for (var i = 1; i < arguments.length; i++) {
            values.push(arguments[i]);
        }
        //這樣獲得了array,和values數組,即可以進一步處理了
    }
};

上面只是打個比方,想要支持不定參數,咱們要作的就是把固定參數和動態參數從 arguments 中分離出來。
可是,咱們這樣寫的話,須要在每一個支持不定參數的函數裏,都 copy 這樣一段代碼,這樣實在不是很優雅。因此須要封裝成一個通用的函數。
咱們直接看看 underscore 是封裝的好了。數組

restArgs 源碼

var restArgs = function(func, startIndex) {
    //startIndex ,表示幾個參數以後即是動態參數
    startIndex = startIndex == null ? func.length - 1 : +startIndex;
    return function() {
        var length = Math.max(arguments.length - startIndex, 0);
        //處理arguments,將動態參數保存進rest數組
        var rest = Array(length);
        for (var index = 0; index < length; index++) {
            rest[index] = arguments[index + startIndex];
        }
        //處理0,1,2三種狀況,這裏要單獨處理,是想優先使用call,由於,call的性能比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不是0,1,2三種狀況,則使用apply調用方法,將args做爲參數,args將爲數組[固定參數 ,rest];
        var args = Array(startIndex + 1);
        for (index = 0; index < startIndex; index++) {
            args[index] = arguments[index];
        }
        args[startIndex] = rest;
        return func.apply(this, args);
    };
};

//這裏without主要的邏輯處理方法,做爲參數,傳給restArgs,在restArgs中處理完參數後,使用call或apply調用邏輯處理方法
// 這時候接受到參數otherArrays,已是一個數組了,包含了以前的動態參數。
_.without = restArgs(function(array, otherArrays) {
    //處理without具體事件
});

underscore.js 中利用 js 高級函數的特性,巧妙的實現了動態參數babel

若是要使某函數支持不定參數,只須要將該函數做爲參數,傳入 restArgs 中便可,例如:app

function addByArray(values) {
    var sum = 0;
    for (var i = 0; i < values.length; i++) {
        sum += values[i];
    }
    return sum;
}
var add = restArgs(addByArray);
//調用:
addByArray([2, 5, 3, 6]); //16
add(2, 5, 3, 6); //16

ES6 不定參數 (...)

ES6 引入了 rest 參數,(形式爲"...變量名"),用於獲取多餘參數,這樣就不須要使用 arguments 對象來實現了函數

function add(...values) {
    let sum = 0;
    for (var val of values) {
        sum += val;
    }
    return sum;
}
add(2, 5, 3); // 10

總結

在 underscore 中,restArgs 只是爲了支持不定參數。實際使用中,也許咱們都是直接使用 ES6,或用 babel 將 ES6 轉成 ES5 來支持不定參數性能

不過,若是是在非 es6 的環境下,知道有這麼一種實現方式,也是挺好的。this

:)rest

相關文章
相關標籤/搜索