不定参数

如何实现不定参数

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


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

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

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

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


  1. _.without = function() {
  2. if (arguments.length > 0) {
  3. var array = arguments[0];
  4. var values = [];
  5. for (var i = 1; i < arguments.length; i++) {
  6. values.push(arguments[i]);
  7. }
  8. //这样得到了array,和values数组,便可以进一步处理了
  9. }
  10. };

上面只是打个比方,想要支持不定参数,我们要做的就是把固定参数和动态参数从 arguments 中分离出来。
但是,我们这样写的话,需要在每个支持不定参数的函数里,都 copy 这样一段代码,这样实在不是很优雅。所以需要封装成一个通用的函数。
我们直接看看 underscore 是封装的好了。

restArgs 源码


  1. var restArgs = function(func, startIndex) {
  2. //startIndex ,表示几个参数之后便是动态参数
  3. startIndex = startIndex == null ? func.length - 1 : +startIndex;
  4. return function() {
  5. var length = Math.max(arguments.length - startIndex, 0);
  6. //处理arguments,将动态参数保存进rest数组
  7. var rest = Array(length);
  8. for (var index = 0; index < length; index++) {
  9. rest[index] = arguments[index + startIndex];
  10. }
  11. //处理0,1,2三种情况,这里要单独处理,是想优先使用call,因为,call的性能比apply要好一点
  12. switch (startIndex) {
  13. case 0:
  14. return func.call(this, rest);
  15. case 1:
  16. return func.call(this, arguments[0], rest);
  17. case 2:
  18. return func.call(this, arguments[0], arguments[1], rest);
  19. }
  20. //如果startIndex不是0,1,2三种情况,则使用apply调用方法,将args作为参数,args将为数组[固定参数 ,rest];
  21. var args = Array(startIndex + 1);
  22. for (index = 0; index < startIndex; index++) {
  23. args[index] = arguments[index];
  24. }
  25. args[startIndex] = rest;
  26. return func.apply(this, args);
  27. };
  28. };
  29. //这里without主要的逻辑处理方法,作为参数,传给restArgs,在restArgs中处理完参数后,使用call或apply调用逻辑处理方法
  30. // 这时候接受到参数otherArrays,已经是一个数组了,包含了之前的动态参数。
  31. _.without = restArgs(function(array, otherArrays) {
  32. //处理without具体事件
  33. });

underscore.js 中利用 js 高级函数的特性,巧妙的实现了动态参数

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


  1. function addByArray(values) {
  2. var sum = 0;
  3. for (var i = 0; i < values.length; i++) {
  4. sum += values[i];
  5. }
  6. return sum;
  7. }
  8. var add = restArgs(addByArray);
  9. //调用:
  10. addByArray([2, 5, 3, 6]); //16
  11. add(2, 5, 3, 6); //16

ES6 不定参数 (...)

ES6 引入了 rest 参数,(形式为"...变量名"),用于获取多余参数,这样就不需要使用 arguments 对象来实现了


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

总结

在 underscore 中,restArgs 只是为了支持不定参数。实际使用中,也许我们都是直接使用 ES6,或用 babel 将 ES6 转成 ES5 来支持不定参数

不过,如果是在非 es6 的环境下,知道有这么一种实现方式,也是挺好的。

:)

来源:https://segmentfault.com/a/1190000017467086

不定参数(rest 参数 ...)的更多相关文章

  1. Python星号*与**用法分析 What does ** (double star/asterisk) and * (star/asterisk) do for parameters? 必选参数 默认参数 可变参数 关键字参数

    python中*号**的区别 - CSDN博客 https://blog.csdn.net/qq_26815677/article/details/78091452 定义可变参数和定义 list 或 ...

  2. C/C++多参数函数参数的计算顺序与压栈顺序

    一.前言 今天在看Thinking in C++这本书时,书中的一个例子引起了我的注意,具体是使用了下面这句 单看这条语句的语义会发现仅仅是使用一个简单的string的substr函数将所得子串pus ...

  3. 做参数可以读取参数 保存参数 用xml文件的方式

    做参数可以读取参数 保存参数 用xml文件的方式 好处:供不同用户保存适合自己使用的参数

  4. Dynamic CRM 2013学习笔记(二十六)报表设计:Reporting Service报表 动态参数、参数多选全选、动态列、动态显示行字体颜色

    上次介绍过CRM里开始报表的一些注意事项:Dynamic CRM 2013学习笔记(十五)报表入门.开发工具及注意事项,本文继续介绍报表里的一些动态效果:动态显示参数,参数是从数据库里查询出来的:参数 ...

  5. C#方法的六种参数,值参数、引用参数、输出参数、参数数组、命名参数、可选参数

    方法的参数有六种,分别是值参数.引用参数.输出参数.参数数组.命名参数.可选参数. 值参数 值参数是方法的默认类型,通过复制实参的值到形参的方式把数据传递到方法,方法被调用时,系统作两步操作: 在栈中 ...

  6. Swift语言中为外部参数设置默认值可变参数常量参数变量参数输入输出参数

    Swift语言中为外部参数设置默认值可变参数常量参数变量参数输入输出参数 7.4.4  为外部参数设置默认值 开发者也可以对外部参数设置默认值.这时,调用的时候,也可以省略参数传递本文选自Swift1 ...

  7. SQL Server 2008 表变量参数(表值参数)用法

    表值参数是 SQL Server 2008 中的新参数类型.表值参数是使用用户定义的表类型来声明的.使用表值参数,可以不必创建临时表或许多参数,即可向 Transact-SQL 语句或例程(如存储过程 ...

  8. (转)Java程序利用main函数中args参数实现参数的传递

    Java程序利用main函数中args参数实现参数的传递 1.运行Java程序的同时,可以通过输入参数给main函数中的接收参数数组args[],供程序内部使用!即当你在Java命令行后面带上参数,J ...

  9. C#分析URL参数获取参数和值得对应列表

    原文: C#分析URL参数获取参数和值得对应列表 /// <summary> /// 分析url链接,返回参数集合 /// </summary> /// <param n ...

  10. Python3基础 函数 收集参数+普通参数 的示例

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...

随机推荐

  1. 教父郭盛华透露:PHP编程语言中多个代码执行缺陷

    黑客无处不在,知名教父级网络安全专家郭盛华透露:“PHP编程语言其核心和捆绑库中的多个高严重性漏洞,其中最严重的漏洞可能允许黑客远程攻击者执行任意代码并破坏目标服务器. 超文本预处理器,通常称为PHP ...

  2. Spring Boot 2.x整合mybatis及druid数据源及逆向工程

    1逆向工程 1)db.properties #============================# #===== Database sttings =====# #=============== ...

  3. Linux下升级安装Python-3.6.9版本

    1.操作系统信息  (1)cat /etc/redhat-releas (2)Red Hat Enterprise Linux Server release 6.0 (Santiago) 2.安装开发 ...

  4. 【JavaScript】数组方法之基础方法

    数组方法之基础方法 Array 对象属性 属性 描述 constructor 返回对创建此对象的数组函数的引用. length 设置或返回数组中元素的数目. prototype 使您有能力向对象添加属 ...

  5. echart-如何将x轴和y轴的原点进行重合???

    设计稿突然让x轴 和y轴重合,我们可以设置图中的这个属性. 不知道还有没有别的设置属性,欢迎评论指出谢谢

  6. 从MapGIS K9到MapGIS 10到MapGIS 10.3 Server

  7. 使用Git上传本地项目到http://git.oschina.net

    本文前言,因倡导开源精神,我也把代码传上了开源社区,可是,当初使用http://git.oschina.net 网站上传代码的时候不知道使用工具.我竟然一个文件一个文件复制粘贴,可费了我好大一个劲儿, ...

  8. MySQL多表查询合并结果union all,内连接查询

    MySQL多表查询合并结果和内连接查询 1.使用union和union all合并两个查询结果:select 字段名 from tablename1 union select 字段名 from tab ...

  9. leetcode-mid-array-31 three sum-NO

    my code:    time limited def threeSum(nums): """ :type nums: List[int] :rtype: List[L ...

  10. Linux下查看分区内目录及文件占用空间容量

    转载linux下使用 du查看某个文件或目录占用磁盘空间的大小   du -ah --max-depth=1     这个是我想要的结果  a显示目录占用的磁盘空间大小,还要显示其下目录和文件占用磁盘 ...