研究下JavaScript中的Rest參数和參数默认值



本文将讨论使 JavaScript 函数更有表现力的两个特性:Rest 參数和參数默认值。



Rest 參数



通常,我们须要创建一个可变參数的函数,可变參数是指函数能够接受随意数量的參数。比如,String.prototype.concat 能够接受不论什么数量的字符串作为參数。使用 Rest 參数,ES6 为我们提供一种新的方式来创建可变參数的函数。



我们来实现一个演示样例函数 containsAll。用于检查一个字符串中是否包括某些子字符串。比如,containsAll("banana", "b", "nan") 将返回true。containsAll("banana", "c", "nan") 将返回 false。



以下是传统的实现方式(參考: http://www.aichengxu.com/view/62895):

function containsAll(haystack) {
for (var i = 1; i < arguments.length; i++) {
var needle = arguments[i];
if (haystack.indexOf(needle) === -1) {
return false;
}
}
return true;
} 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
參数的实现方式:

//http://www.aichengxu.com
function containsAll(haystack, ...needles) {
for (var needle of needles) {
if (haystack.indexOf(needle) === -1) {
return false;
}
}
return true;
} 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。

參数的默认值



通常,调用一个函数时,不须要调用者传递全部可能的參数,那些没有传递的參数都须要一个合理的默认值。

JavaScript 对那些没有传递的參数都有一个固定的默认值 undefined。

在 ES6 中,引入了一种新方法来指定随意參数的默认值。



看以下样例:

function animalSentence(animals2="tigers", animals3="bears") {
return `Lions and ${animals2} and ${animals3}! Oh my!`;
} 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!`;
} 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) {...}

等同于

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

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

抛弃 arguments



通过 Rest 參数和參数的默认值,我们能够全然抛弃 arguments 对象。使我们的代码可读性更高。此外,arguments 对象也加深了优化 JavaScript 的难题。

希望以上两个新特性能够全然代替 arguments。作为第一步,在使用 Rest 參数或參数的默认值时,请避免使用 arguments 对象,假如 arguments 对象还不会马上被移除,或者永远不会。那么也最好是避免在使用 Rest 參数或參数默认值时使用 arguments 对象。



兼容性



Firefox 15 以上的版本号已经支持这两个新特性。然而,除此之外,还没有其它不论什么浏览器支持。近期,V8 的实验环境加入了对 Rest 參数的支持,而參数默认值另一个 issue。JSC 也对 Rest 參数和參数默认值提了一些 issue。



Babel 和 Traceur 这两个编译器都已经支持了參数默认值。所以你能够大胆使用。



结论



虽然从技术层面上看,这两个新特性在并没有给函数引入新的行为,但它们能够使一些函数的声明更具表现力和可读性。

研究下JavaScript中的Rest參数和參数默认值的更多相关文章

  1. (一)javascript中的数组index属性——获取数组的索引值

    例如:要做到这样的效果 点击每个选项时,会显示不同的div. 我们的做法:在javascript中,先把所有的div的display设置为none,然后在根据当前的数组里的索引值进行一个显示div的过 ...

  2. js中input文本框设置和移除默认值

    这里想实现的效果是:设置和移除文本框默认值,如下图鼠标放到文本框中的时候,灰字消失. 1.可以用简单的方式,就是给input文本框加上onfocus属性,如下代码: <input id=&quo ...

  3. bootstrapValidator验证的remote中data属性里获取select一直是默认值

    budgetEditionNo:{ message:'版本号输入不正确' , validators:{ notEmpty:{ message:'版本号不能为空,请填写' } , remote:{ ur ...

  4. Apollo 中配置String、Map和List和默认值

    摘要:在Apollo 中,配置String.Map和List等类型的信息,同时设置默认值. 综述   随着业务需求的变更,需要在Apollo中配置一个Map<String, List>类型 ...

  5. javascript中=,==,与===的区别;以及特殊值NaN的讲解

    1.在js中"="是作为赋值.var a;  a=3:给a赋值为3. 2."=="称作相等,"==="被称作严格相等.当使用"== ...

  6. javascript中json对象与字符串互转及取值

    一.   json字符串转换为javascript对象,并取值 var answer = '{"id":0}' var value= JSON.parse(answer); //转 ...

  7. myeclipse下拷贝的项目,tomcat下部署名称和导出为war包的名称默认值修改

    拷贝一个项目,作为一个新的项目,给它换了名字,这时候默认的部署名称等都是原来项目的,这时候要在属性里面修改一下.

  8. SqlServer中 将某个表的某个字段改个默认值

    ALTER TABLE [dbo].[表名] ADD CONSTRAINT [DF_表名_列名] DEFAULT ((默认值)) FOR [列名] ALTER TABLE QA_API ADD CON ...

  9. JavaScript 中的数据类型

    Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...

随机推荐

  1. 洛谷——P1306 斐波那契公约数

    P1306 斐波那契公约数 题目描述 对于Fibonacci数列:1,1,2,3,5,8,13......大家应该很熟悉吧~~~但是现在有一个很“简单”问题:第n项和第m项的最大公约数是多少? 输入输 ...

  2. Add and Search Word - Data structure design - LeetCode

    Design a data structure that supports the following two operations: void addWord(word) bool search(w ...

  3. jquery dataTable 获取某行数据

    DataTable API table.row(rowSelector [,modifier]) 注table是dataTable的对象 该方法有两个默认参数 第一个是选择器 第二个是可选的 请注意, ...

  4. Android Retrofit使用教程(二)

    上一篇文章讲述了Retrofit的简单使用,这次我们学习一下Retrofit的各种HTTP请求. Retrofit基础 在Retrofit中使用注解的方式来区分请求类型.比如@GET("&q ...

  5. 对象第复制operator=

    类机制中有默认的对象复制操作符=,自定义对象复制需要注意一个问题,如果有遇到指针指向的资源是需要释放的,这时需要毫不留情释放,否则内存空间的泄露就不可避免.复制操作与拷贝构造函数的参数是一致的,只是在 ...

  6. java模拟http的Get/Post请求,并设置ip与port代理

    本文涉及3个基本点: 1.因为很多公司的内网都设有代理,浏览器通过ip与port上网,而java代码模拟http get方式同样需要外网代理: 2.Java实现http的Get/Post请求代码: 3 ...

  7. 2017.2.20 activiti实战--第五章--用户与组及部署管理(一)用户与组

    学习资料:<Activiti实战> 第五章 用户与组及部署管理(一)用户与组 内容概览:讲解activiti中内置的一套用户.组的关系,以及如何通过API添加.删除.查询. 5.1 用户与 ...

  8. 从头认识java-14.2 进一步了解数组

    这一章节我们来全面了解一下数组. 1.数组在初始化之前.我们不能使用他的引用来做不论什么事情. package com.ray.ch14; public class Test { public sta ...

  9. Mysql 性能监控及调优

    死锁概念: 两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象 1.监控死锁(innotop): (1) 启用 innodb_status_file 在/etc/my.cnf添加如 ...

  10. ANT安装及配置

    首先,到http://ant.apache.org/找到合适的版本下载. 其次,讲下载的zip包解压,得到的目录拷贝到硬盘,如C:\apache-ant-1.9.4 其三,设置环境变量 ANT_HOM ...