资讯专栏INFORMATION COLUMN

不定参数(rest 参数 ...)

Lucky_Boy / 2434人阅读

摘要:但是,我们这样写的话,需要在每个支持不定参数的函数里,都这样一段代码,这样实在不是很优雅。实际使用中,也许我们都是直接使用,或用将转成来支持不定参数不过,如果是在非的环境下,知道有这么一种实现方式,也是挺好的。

不定参数 如何实现不定参数

使用过 underscore.js 的人,肯定都使用过以下几个方法:

_.without(array, *values) //返回一个删除所有values值后的array副本
_.union(*arrays) //返回传入的arrays(数组)并集
_.difference(array, *others)//返回来自array参数数组,并且不存在于other 数组
...

这些方法都有一个共同点,就是可以传入不定数量的参数,例如,我想删除掉 array 中的 value1,value2 ,可以这样使用 , _.without(array,value1,value2);

那么,这个需要怎样才能做到呢?

我们知道,js 中 function 里面,有一个 arguments 参数,它是一个类数组,里面包含着调用这个方法的所有参数,所以可以这样处理:

_.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 高级函数的特性,巧妙的实现了动态参数

如果要使某函数支持不定参数,只需要将该函数作为参数,传入 restArgs 中即可,例如:

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 的环境下,知道有这么一种实现方式,也是挺好的。

:)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100261.html

相关文章

  • es6 -- 默认参数Default,不定参数Rest,扩展运算符Spread详解

    摘要:将数组中的每个元素展开为函数参数扩展运算符取代方法的一个实际的例子,应用方法,简化求出一个数组最大元素的写法。 欢迎访问我的个人博客:http://www.xiaolongwu.cn 前言 记录一下在实际开发中,很有用的三个es6的新方法 用法详解 默认参数 function f(x, y=13) { // 如果没有传入y或传入了undefined,y的默认值为13 retur...

    Betta 评论0 收藏0
  • 初学python,调用固定参,不固定参函数遇到的问题(持续更新)

    摘要:即,双星号参数接收的参数作为字典。在有些情况下,单星号函数参数和双星号函数参数是一起使用的,定义如下总结默认值函数参数。双星号函数参数。 函数调用时的参数传递方式:(调用函数) 传递方式有以下四种: 位置传参 序列传参 关键字传参 字典关键字传参---------------------------------------------------yu--- (1)位置传参: 实际参...

    bingo 评论0 收藏0
  • ES6语法之函数的扩展

    摘要:函数的扩展函数参数的默认值之前,不能直接为函数的参数指定默认值,只能采用变通的方法。箭头函数引入了一种新的函数,叫做箭头函数。箭头函数和普通函数的行为非常相似,但是在语法构成上非常不同。意味着函数内的的值是全局对象,不是对象。 函数的扩展 函数参数的默认值 ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法。 function log(x, y) { y = y ||...

    Clect 评论0 收藏0
  • es6的解构赋值、扩展运算符、rest参数使用

    摘要:模板字符串甚至还能嵌套解构赋值允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。运算符使用场景应该稍少一些,主要是处理不定数量参数,可以避免对象的使用。 es6中较为常用的书写风格 为了书写的方便,es6中提出了很多比较友好的书写方式,其中最为常见的属于以下几个: 字符串模板 `abcdef${test}` 解构赋值 let [a, b, c] = [1,...

    xuweijian 评论0 收藏0
  • 详解call bind apply - 区别/使用场景/es6实现/es3实现

    摘要:的区别接收数组一连串参数返回一个函数的使用场景将类数组含有属性的对象转化为数组类数组例如通过获取的元素含有属性的对象具有属性,并且可以通过下标来访问其中的元素,但是没有中的等方法。 call,apply,bind的区别 apply接收数组 func.apply(obj, [arus]) call一连串参数 func.call(obj, param1, param2....) bind...

    Alex 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<