Rest 参数

通常,我们需要创建一个可变参数的函数,可变参数是指函数可以接受任意数量的参数。例如,String.prototype.concat 可以接受任何数量的字符串作为参数。使用 Rest 参数,ES6 为我们提供一种新的方式来创建可变参数的函数。
我们来实现一个示例函数 containsAll,用于检查一个字符串中是否包含某些子字符串。例如,containsAll("banana", "b", "nan") 将返回true,containsAll("banana", "c", "nan") 将返回 false。
下面是传统的实现方式:

function containsAll(haystack) {for (var i = 1; i < arguments.length; i++) {var needle = arguments[i];if (haystack.indexOf(needle) === -1) {return false;}}return true;
}

该实现用到了 arguments 对象,该对象是一个类数组对象,包含函数被调用时的实参列表。这段代码正是我们想要的,但其可读性却不是最优的。函数只有一个形参 haystack,所以不可能一看就知道该函数需要多个参数,并且在遍历 arguments 时,需要特别注意遍历的开始索引为 1 ,而不是常见的 0,因为 arguments[0] 就是函数定义时的形参 haystack。如果我们想在 haystack 参数之前或之后添加一些参数,我们不得不更新内部的循环。Rest 参数解决了这些问题,下面是 使用 Rest 参数的实现方式:

function containsAll(haystack, ...needles) {for (var needle of needles) {if (haystack.indexOf(needle) === -1) {return false;}}return true;
}

以上两个实现都满足了我们的需求,但后者包含一个特殊的 ...needles 语法。我们来看看调用 containsAll("banana", "b", "nan") 时的细节,参数 haystack 和以往一样,将用函数的第一个实参填充,值为 "banana",needles 前面的省略号表示它是一个 Rest 参数,剩余的所有实参将被放入一个数组中,并将该数组赋给 needles 遍量。在这个调用中,needles 的值为 ["b", "nan"]。然后,就是正常的函数执行了。
只能将函数的最后一个函数作为 Rest 参数,在函数被调用时,Rest 参数之前的参数都将被正常填充,之外的参数将被放入一个数组中,并将该数组作为 Rest 参数的值,如果没有更多的参数,那么 Rest 参数的值为一个空数组 [],Rest 参数的值永远都不会是 undefined。

实现Rest参数的函数 restArgs

var restArgs = function (func, startIndex) {// rest参数从哪里开始,如果没有,则默认视函数最后一个参数为rest参数// 注意, 函数对象的length属性, 揭示了函数的参数个数/*ex: function add(a,b) {return a+b;}console.log(add.length;) // 2*/startIndex = startIndex == null ? func.length - 1 : +startIndex;// 返回一个支持rest参数的函数return function () {// 校正参数, 以免出现负值情况var length = Math.max(arguments.length - startIndex, 0);// 为rest参数开辟数组存放var rest = Array(length);// 假设参数从2个开始: func(a,b,*rest)// 调用: func(1,2,3,4,5); 实际的调用是:func.call(this, 1,2, [3,4,5]);for (var index = 0; index < length; index++) {rest[index] = arguments[index + startIndex];}// 根据rest参数不同, 分情况调用函数, 需要注意的是, rest参数总是最后一个参数, 否则会有歧义switch (startIndex) {case 0:// call的参数一个个传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);}// 如果不是上面三种情况, 而是更通用的(应该是作者写着写着发现这个switch case可能越写越长, 就用了apply)var args = Array(startIndex + 1);// 先拿到前面参数for (index = 0; index < startIndex; index++) {args[index] = arguments[index];}// 拼接上剩余参数args[startIndex] = rest;return func.apply(this, args);};
};

参数的默认值

通常,调用一个函数时,不需要调用者传递所有可能的参数,那些没有传递的参数都需要一个合理的默认值。JavaScript 对那些没有传递的参数都有一个固定的默认值 undefined。在 ES6 中,引入了一种新方法来指定任意参数的默认值。
看下面例子:

function animalSentence(animals2="tigers", animals3="bears") {return `Lions and ${animals2} and ${animals3}! Oh my!`;
}

在每个参数的 = 后面是一个表达式,指定了参数未传递时的默认值。所以,animalSentence() 返回 "Lions and tigers and bears! Oh my!", animalSentence("elephants") 返回 "Lions and elephants and bears! Oh my!", animalSentence("elephants", "whales") 返回 "Lions and elephants and whales! Oh my!"。
参数默认值需要注意的几个细节:与 Python 不一样的是,参数默认值的表达式是在函数调用时从左到右计算的,这意味着表达式可以使用前面已经被填充的参数。例如,我们可以将上面的函数变得更有趣一点:

function animalSentenceFancy(animals2="tigers",animals3=(animals2 == "bears") ? "sealions" : "bears")
{return `Lions and ${animals2} and ${animals3}! Oh my!`;
}

那么,animalSentenceFancy("bears") 将返回 "Lions and bears and sealions. Oh my!"。
传递 undefined 等同于没有传递该参数。因此,animalSentence(undefined, "unicorns") 将返回 "Lions and tigers and unicorns! Oh my!"。如果没有为一个参数指定默认值,那么该参数的默认值为 undefined,所以

function myFunc(a=42, b) {...}

等同于

function myFunc(a=42, b=undefined) {...}

原文链接

ES6:Rest 参数和参数默认值【转】相关推荐

  1. java 默认参数_Java 方法的参数可以有默认值吗?

    Java 方法的参数可以有默认值吗? 例如 void method(String p1, int p2, bool p3=false); 回答 Java不支持这种特性, 如果你真的有需求,你可以 通过 ...

  2. ADO.NET+Access: 3,参数 @departmentName 没有默认值

    ylbtech-Error-ADO.NET+Access: 3,参数 @departmentName 没有默认值. 1.A,错误代码返回顶部 3,参数 @departmentName 没有默认值. 1 ...

  3. 一行命令获取当前JVM所有可设置的参数以及当前默认值

    2019独角兽企业重金招聘Python工程师标准>>> 一行命令获取当前JVM所有可设置的参数以及当前默认值 博客分类: java jvm 一行命令获取当前JVM所有可设置的参数以及 ...

  4. C#使用OleDB操作ACCESS插入数据时提示:参数 @p_Contract 没有默认值

    C#使用OleDB操作ACCESS插入数据时提示:参数 @p_Contract 没有默认值 OleDbParameter param = new OleDbParameter("" ...

  5. java xms xmx 默认值_JVM启动参数-Xmx的默认值是多少?

    1:JVM启动的时候,如果我不加-Xmx参数,可已分配给堆的最大内存是多少? 2:JDK1.5和JDK1.6等不同版本,Xmx参数的默认值是一样的吗?有什么区别? 3:xmx默认值与操作系统类型.位数 ...

  6. 判断参数并赋予默认值

    一个有用的code,判断用户给的参数(UserEnterFile)是否存在,如果不存在则用(EnterNothing)作为默认值 filename=${UserEnterFile:-"Ent ...

  7. JS方法参数设置为默认值的几种方式

    绪论 写JS方法会碰到参数不固定的时候,把每个参数都赋值又感觉麻烦,就想有没有办法设置个默认值呢?果然有解决方法.在此记录一下. 正文 <!DOCTYPE html> <div la ...

  8. 【Python】一篇文章学会def定义函数的可选参数,默认参数,有默认值的可选参数(保姆级注释)

    目录 API说明: 固定参数例程 默认参数例程 可选参数元组例程 有默认值的可选参数r例程 综合例程 全文代码合集 总结 欢迎关注 『Python』 系列,持续更新中 欢迎关注 『Python』 系列 ...

  9. java xms xmx 默认值,JVM启动参数-Xmx的默认值是多少?

    你也可以在程序里试试打印 Runtime.getRuntime().maxMemory() 的值 看看是多少 官网说明: https://docs.oracle.com/javase/8/docs/t ...

  10. mysql存储过程默认参数_mysql 存储过程 默认值解决办法

    mysql 存储过程 默认值 //在mssql的实现方式 CREATE   PROCEDURE   [dbo].[InsertNode] @Name     nvarchar(50)   =   N ...

最新文章

  1. python django框架如何导出_python框架django的数据库的正向生成和反向生成
  2. 区块链架构、跨链和演进
  3. 14.11类的成员修饰符
  4. Zookeeper: Zookeeper架构及FastLeaderElection机制
  5. 蔚来ES8正式交付售价46.8万元起 与Model系相比扛打吗?
  6. android 反编译工具_【Android APK分析工具】
  7. 如何用JavaScript搭建神经网络?90分钟免费课程,上手可操作丨教程
  8. 实习成长之路:MySQL十三: count(*)这么慢,我该怎么办?为什么那么慢?
  9. paip.ASP 开发调试大总结
  10. 易软门诊管理软件php,易软门诊管理系统
  11. 普歌-nuxt.js基础
  12. 人民币对PHP金汇率,PHP货币是哪个国家的,和人民币的汇率怎么样,3万人民币能兑换多少?...
  13. 波浪线html,js中的波浪线符号作用(按位非(~)符号)
  14. matlab雨中行走代码,雨中行走数学建模雨中行走数学建模.doc
  15. 如何成为优秀的网络安全工程师(转载)
  16. 如何在线重装win7系统,一起来看看
  17. word表格中 英文排版
  18. 击碎“基因决定论”和“1万小时理论”认知误区!这本书告诉你怎么快速成长!
  19. docker容器使用docker-squash压缩体积
  20. pdf.net sod oracle,SOD: 原PDF.NET框架将成为一个全功能的企业开发框架,而 SOD框架将是PDF.NET开发框架下面的 “数据开发框架...

热门文章

  1. python server酱_教你如何使用Python向手机发送通知(IFTTT)
  2. Linux系统和windows系统mysql5.7.32的下载
  3. MySQL中向下查询_mysql
  4. mysql my.cnf中忽略大小写_修改my.cnf ,使mysql 的表面不区分大小写
  5. php链接没有下划线,html超链接怎么去掉下划线
  6. html怎么在服务器环境,如何搭建node服务器环境?
  7. oracle统计每个类别,Oracle统计分析函数集之一
  8. css flex布局 padding,css三栏布局的三种实现方式(圣杯布局、双飞翼布局、Flex布局)...
  9. android滚动悬停布局,android布局滑动到顶端悬浮,录音
  10. mysql词法分析antlr4_词法分析器和语法分析器的界线 - ANTLR 4 简明教程