研究下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. sokect数据压缩实现

    上一篇文章说到了用Java Socket来传输对象,但是在有些情况下比如网络环境不好或者对象比较大的情况下需要把数据对象进行压缩然后在传输,此时就需要压缩这些对象流,此时就 可以GZIPInputSt ...

  2. 【DirectX SDK Extra】提示缺少Qedit.h问题 (转)

    原文转自 http://blog.csdn.net/joeblackzqq/article/details/10944005 DirectX 9.0 SDK 开发包以及扩展包下载(February 2 ...

  3. 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---37

    以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:

  4. 《手把手教你学C语言》学习笔记(8)--- 运算符和表达式

    C语言编程的核心是指针和库,而库的核心就是函数,函数的基本组成部分就是语句. C语言合法表达式加上分号(语句结束符)构成C函数的基本部分语句.如果只有分号没有表达式就构成空语句,空语句常常用来形成占位 ...

  5. anaconda 安装

    1. 安装: 参考博客:https://blog.csdn.net/qq_36851515/article/details/82956150 2. 更新包: 更新失败:conda httperror ...

  6. linux创建和查看用户命令

    1.创建一个叫做hadoop的用户,用户的目录是/home/hadoop useradd -d /home/hadoop hadoop 2.输入密码 passwd hadoop 3.删除用户 user ...

  7. Codeforces Gym101473 A.Zero or One (2013-2014 ACM-ICPC Brazil Subregional Programming Contest)

    代码: #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #i ...

  8. python-字符转换遇到的问题

    1,异常: 'ascii' codec can't encode characters 字符集的问题,在文件前加两句话:import sysreload(sys)sys.setdefaultencod ...

  9. 对动态规划(Dynamic Programming)的理解:从穷举开始(转)

    转自:http://janfan.cn/chinese/2015/01/21/dynamic-programming.html 动态规划(Dynamic Programming,以下简称dp)是算法设 ...

  10. NOI模拟题4 Problem A: 生成树(mst)

    Solution 我们考虑答案的表达式: \[ ans = \sqrt{\frac{\sum_{i = 1}^{n - 1} (w_i - \overline{w})^2}{n - 1}} \] 其中 ...