作者 Jason Orendorff  github主页  https://github.com/jorendorff

不定参数

我们通常使用可变参函数来构造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的引擎不会立即移除对它的支持,当然,现在更推荐使用不定参数和默认参数。

浏览器支持

Firefox早在第15版的时候就支持了不定参数和默认参数。

不幸的是,尚未有其它已发布的浏览器支持不定参数和默认参数。V8引擎最近增添了针对不定参数的实验性的支持,并且有一个开放状态的V8 issue给实现默认参数使用,JSC同样也有一个开放的issue来给不定参数默认参数使用。

BabelTraceur编译器都支持默认参数,所以从现在起就可以开始使用。

文后盘点

尽管技术上不支持任何新的行为,不定参数和参数默认值还是可以使一些JavaScript函数定义更富有表现力并且更加可读。调用时自然也更加舒爽!

深入浅出ES6(五):不定参数和默认参数的更多相关文章

  1. 深入浅出ES6:不定参数和默认参数

    不定参数 我们通常使用可变参函数来构造API,可变参函数可接受任意数量的参数.例如,String.prototype.concat方法就可以接受任意数量的字符串参数.ES6提供了一种编写可变参函数的新 ...

  2. ES6中的Rest参数和默认参数

    ES6中的Rest参数和默认参数 Rest参数 一个例子 编写一个函数, 用来判断, 某个字符串中, 是否其他的字符串, 如果第一参数以后的字符串, 都包含在第一参数中, 都包含在, 就返回true ...

  3. python函数中的参数(关键字参数,默认参数,位置参数,不定长参数)

    默认参数:定义函数的时候给定变量一个默认值. def num(age=1): 位置参数:调用函数的时候根据定义函数时的形参位置和实参位置进行引用. 关键字参数:如果定义的函数中含有关键字参数,调用函数 ...

  4. Python 必选参数,默认参数,可变参数,关键字参数和命名关键字参数

    Py的参数还真是多,用起来还是很方便的,这么多参数种类可见它在工程上的实用性还是非常广泛的. 挺有意思的,本文主要参照Liaoxuefeng的Python教程. #必选参数 def quadratic ...

  5. python 必选参数、默认参数、可变参数和、关键字参数

    转自:https://www.liaoxuefeng.com/wiki/897692888725344/897693568201440 可变参数 在Python函数中,还可以定义可变参数.顾名思义,可 ...

  6. ES6新特性(函数默认参数,箭头函数)

    ES6新特性之 函数参数的默认值写法 和 箭头函数. 1.函数参数的默认值 ES5中不能直接为函数的参数指定默认值,只能通过以下的变通方式:   从上面的代码可以看出存在一个问题,当传入的参数为0或者 ...

  7. [js高手之路] es6系列教程 - 函数的默认参数详解

    在ES6之前,我们一般用短路表达式处理默认参数 function show( a, b ){ var a = a || 10; var b = b || 20; console.log( a, b ) ...

  8. SE6 不定参数和默认参数详解和使用细节

    在SE5以前我们通常通过arguments类数组对象来引用不定形参,SE6则使用了一种叫做不定参数的写法,比起隐式的arguments要直观的多. 不定参数使用...参数名来指定一个不定参数,参数名指 ...

  9. 如何在ES5与ES6环境下处理函数默认参数

    函数默认值是一个很提高鲁棒性的东西(就是让程序更健壮)MDN关于函数默认参数的描述:函数默认参数允许在没有值或undefined被传入时使用默认形参. ES5 使用逻辑或||来实现 众所周知,在ES5 ...

随机推荐

  1. WindowsPhone8 数据库增删改查

    今天第一次在博客园发表文章,如果有的地方写的不对,还请大家指出! 1.这就是一个简单wp8数据库增删改查 1.创建数据表Person [Table] public class Person : INo ...

  2. 真正理解KMP算法

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4403560.html 所谓KMP算法,就是判断一个模式串是否是一个字符串的子串,通常的算法当 ...

  3. IE8浏览器跨域接口访问异常的解决办法

    IE8版本以下浏览器绝对是一个神奇的存在,忙碌好久,万事具备,居然在ajax调用接口的时候直接爆炸 陈述一下问题 首先是有这样一个接口,请求类型POST,入参JSON,出参JSON,jQuery aj ...

  4. HTML5 INPUT新增属性

    HTML5的input标签新增了很多属性,也是让大家非常兴奋的一件事,用简单的一个属性搞定以前复杂的JS验证.input新增的这些属性,使得html和js的分工更明确了,使用起来十分舒畅.我们先看下i ...

  5. RAID 0+1

    正如其名字一样RAID 0+1是RAID 0和RAID 1的组合形式,也称为RAID 01. 以四个磁盘组成的RAID 0+1为例,其数据存储方式如图所示:RAID 0+1是存储性能和数据安全兼顾的方 ...

  6. 30个HTML5学习资源

    早在几个星期前,Adobe就发布了Dreamweaver CS5 HTML5 Pack的预览版下载.众所周知,HTML5在互联网领域掀起了一场大论战,并让Adobe的日子很难熬.HTML5致力于为前端 ...

  7. ZK framework on Java

    Quick start: https://www.zkoss.org/documentation Live demo: https://www.zkoss.org/zkdemo/file_handli ...

  8. PHP 图片文件上传代码

    通过 PHP,可以把文件上传到服务器.里面加入一些图片的判断,如果不加判断文件的类型就可以上传任意格式的文件. 为了网站的安全,肯定不让上传php文件,如果有人进入你的后台,上传了一个php文件,你的 ...

  9. JavaScript 垃圾回收机制分析

    同C# .Java一样可以手工调用垃圾回收程序,但是由于其消耗大量资源,而且手工调用的不会比浏览器判断的准确,所以不推荐手工调用垃圾回收.   最近精力主要用在了Web 开发上,读了一下<Jav ...

  10. lnmp下用phpize动态安装PHP模块/扩展(不需要重装PHP)

    安装前 安装前建议先执行 /usr/local/php/bin/php -m (此命令显示目前已经安装好的PHP模块)看一下,要安装的模块是否已安装.然后下载当前PHP版本的源码并解压. 本文以ima ...