[ES6深度解析]9:Rest参数和默认值
2021-08-24 20:44
190 查看
Rest参数
在创建API时,一个常见的需求是创建可变参数函数(参数个数不确定),这个函数可以接受任意数量的参数。例如,
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之前或之后添加另一个参数,我们必须记住更新for循环。Rest参数解决了这两个问题。下面是一个使用rest参数的
containsAll的自然ES6实现:
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
缺省参数(Default parameters)
通常,函数不需要调用者传递所有可能的参数,对于未传递的参数,可以使用合理的默认值。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) {...}
抛弃arguments
现在我们已经看到,rest形参和默认值可以替代
arguments对象的使用,删除
arguments通常会使代码更易于阅读。除了有损可读性之外,
arguments对象的魔力还会给优化JavaScript vm带来麻烦。
相关文章推荐
- ES6(六: 函数扩展)(默认值,rest参数,扩展运算符)
- C++深度解析 函数参数的扩展---函数参数的默认值,函数默认参数的规则,函数占位参数(6)
- ES6知识点整理之函数数组参数的默认值及其解构应用示例
- ES6 随记(3.4.1)-- 函数的拓展(参数默认值,扩展运算符)
- Python函数参数深度解析
- ES6------rest参数
- c# 深度解析方法参数的关键字ref
- ES6 函数参数默认值 default
- django-rest-framework解析请求参数过程详解
- ES6 Rest参数
- 在es6中,对rest参数和扩展运算符的理解(待更新)
- es6 函数参数的默认值与解构赋值的默认值结合使用理解
- ES6|扩展运算符/Rest参数——“...“
- 【技术】C#入门:深度解析方法参数的关键字ref
- ES6学习——新的语法:函数参数默认值
- ES6笔记之参数默认值(译)
- ES6 函数的扩展 rest 参数
- 研究下JavaScript中的Rest参数和参数默认值
- ES6新特性---模板字符串、参数默认值
- [ES6深度解析]13:let const