深入浅出ES6:不定参数和默认参数
不定参数
我们通常使用可变参函数来构造API,可变参函数可接受任意数量的参数。例如,String.prototype.concat方法就可以接受任意数量的字符串参数。ES6提供了一种编写可变参函数的新方式——不定参数。
我们通过一个简单的可变参数函数containsAll给大家演示不定参数的用法。函数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,我们无法一眼就看出这个函数实际上接受了多个参数。另外,我们一定要注意,应该从1开始迭代,而不是从0开始,因为arguments[0]相当于参数haystack。如果我们想要在haystack前后添加另一个参数,我们一定要记得更新循环体。不定参数恰好可以解决可读性与参数索引的问题。下面是用ES6不定参数特性实现的containsAll函数:
function containsAll(haystack, ...needles) {
for (var needle of needles) {
if (haystack.indexOf(needle) === -1) {
return false;
}
}
return true;
}
这一版containsAll函数与前者有相同的行为,但这一版中使用了一个特殊的...needles语法。我们来看一下调用containsAll("banana", "b", "nan")之后的函数调用过程,与之前一样,传递进来的第一个参数"banana"赋值给参数haystack,needles前的省略号表明它是一个不定参数,所有传递进来的其它参数都被放到一个数组中,赋值给变量needles。对于我们的调用示例而言,needles被赋值为["b", "nan"],后续的函数执行过程一如往常。(注意啦,我们已经使用过ES6中for-of循环。)
在所有函数参数中,只有最后一个才可以被标记为不定参数。函数被调用时,不定参数前的所有参数都正常填充,任何“额外的”参数都被放进一个数组中并赋值给不定参数。如果没有额外的参数,不定参数就是一个空数组,它永远不会是undefined。
默认参数
通常来说,函数调用者不需要传递所有可能存在的参数,没有被传递的参数可由感知到的默认参数进行填充。JavaScript有严格的默认参数格式,未被传值的参数默认为undefined。ES6引入了一种新方式,可以指定任意参数的默认值。
下面是一个简单的示例 :
function animalSentence(animals2="tigers", animals3="bears") {
return `Lions and ${animals2} and ${animals3}! Oh my!`;
}
默认参数的定义形式为[param1[ = defaultValue1 ][, ..., paramN[ = defaultValueN ]]],对于每个参数而言,定义默认值时=后的部分是一个表达式,如果调用者没有传递相应参数,将使用该表达式的值作为参数默认值。相关示例如下:
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
现在我们已经看到了arguments对象可被不定参数和默认参数完美代替,移除arguments后通常会使代码更易于阅读。除了破坏可读性外,众所周知,针对arguments对象对JavaScript虚拟机进行的优化会导致一些让你头疼不已的问题。
我们期待着不定参数和默认参数可以完全取代arguments,要实现这个目标,标准中增加了相应的限制:在使用不定参数或默认参数的函数中禁止使用arguments对象。曾经实现过arguments的引擎不会立即移除对它的支持,当然,现在更推荐使用不定参数和默认参数。
深入浅出ES6:不定参数和默认参数的更多相关文章
- 深入浅出ES6(五):不定参数和默认参数
作者 Jason Orendorff github主页 https://github.com/jorendorff 不定参数 我们通常使用可变参函数来构造API,可变参函数可接受任意数量的参数.例 ...
- ES6中的Rest参数和默认参数
ES6中的Rest参数和默认参数 Rest参数 一个例子 编写一个函数, 用来判断, 某个字符串中, 是否其他的字符串, 如果第一参数以后的字符串, 都包含在第一参数中, 都包含在, 就返回true ...
- python函数中的参数(关键字参数,默认参数,位置参数,不定长参数)
默认参数:定义函数的时候给定变量一个默认值. def num(age=1): 位置参数:调用函数的时候根据定义函数时的形参位置和实参位置进行引用. 关键字参数:如果定义的函数中含有关键字参数,调用函数 ...
- Python 必选参数,默认参数,可变参数,关键字参数和命名关键字参数
Py的参数还真是多,用起来还是很方便的,这么多参数种类可见它在工程上的实用性还是非常广泛的. 挺有意思的,本文主要参照Liaoxuefeng的Python教程. #必选参数 def quadratic ...
- python 必选参数、默认参数、可变参数和、关键字参数
转自:https://www.liaoxuefeng.com/wiki/897692888725344/897693568201440 可变参数 在Python函数中,还可以定义可变参数.顾名思义,可 ...
- SE6 不定参数和默认参数详解和使用细节
在SE5以前我们通常通过arguments类数组对象来引用不定形参,SE6则使用了一种叫做不定参数的写法,比起隐式的arguments要直观的多. 不定参数使用...参数名来指定一个不定参数,参数名指 ...
- es6笔记 day2---函数默认参数、箭头函数、剩余参数
函数变化: 1.函数默认参数 2.函数参数默认是已经定义了,不能再使用let.const声明 3.扩展运算符.rest运算符 ...就是扩展运算符,它的作用就是把数组给展开 结合函数使用传参,也可以将 ...
- Javascript变长参数和默认参数
/* javascript 变长参数 * 实参少于形参: 剩下的参数如果没有默认值,将解析为undefined * 实参多于形参: 剩下的实参可以通过 "实参对象"-argumen ...
- matlab 可变参数与默认参数设置
1. 基本思路 矩阵矢量化编程,而不是循环和遍历: GPU 并行计算: 使用稀疏矩阵: 2. 实践 可变长输入参数,输出参数,需要解析(使用大括号进行索引): varargin varargout 函 ...
随机推荐
- 将分支推送到远程存储库时遇到错误: Git failed with a fatal error. TaskCanceledException encountered.
解决:https://blog.csdn.net/dw33xn/article/details/79951714 修改下配置文件即可
- ionic3 生命周期 之 ionViewWillLeave 坑
ionic3 生命周期 ionViewWillLeave,当页面关闭离开时 执行的事件, 从页面根部跳转 this.appCtrl.getRootNav().setRoot() 方法离开时是 不执行 ...
- 使用dbms_profiler收集存储过程每步执行时间
最近和优化团队的专家学到一个很有意义的内置包:dbms_profiler,专门用于分析Oracle存储过程中的各段代码的时间开销情况,从而快速找到性能瓶颈的步骤. 1.sys创建dbms_profil ...
- FB面经prepare: Count the number of Vector
给一个超级大的排好序的vector [abbcccdddeeee]比如,要求返回[{,a}, {,b}, {,c}, {,d}, {,e}......]复杂度要优于O(N) 分析: 如果是binary ...
- redis----------基本命令使用
1.查看全部缓存数据的key keys * 2.清空当前redis数据库缓存 flushdb (redis默认由16个库(0~15号). 且默认使用的是0号库.库之间的切换使用select命令例如: ...
- SQLServer无法打开用户默认数据库 登录失败错误4064的解决方法
无法打开用户默认数据库,登录失败,其原因是登录帐户的默认数据库被删除. 解决办法是使用管理员帐户修改此登录帐户的默认数据库. 1.使用管理员帐号登入企业管理器,在“对象资源管理器”中,展开“安全性”— ...
- 蓝桥杯c/c++省赛真题——日志统计
标题:日志统计 [问题描述]小明维护着一个程序员论坛.现在他收集了一份"点赞"日志,日志共有N行.其中每一行的格式是:ts id 表示在ts时刻编号id的帖子收到一个" ...
- vue-cli教程
转:https://jspang.com/post/vue-cli2.html#toc-5ca
- Delphi中PointerMath指令
Type Switch Syntax {$POINTERMATH ON} or {$POINTERMATH OFF} Default {$POINTERMATH OFF} Sc ...
- python & mysql 操作(compare_sum_fee)
[1]源码 工作中涉及的python工具源码实现 费用比较工具源码: #!/usr/bin/python3 #coding = utf-8 import time, sqlite3, datetime ...