研究下JavaScript中的Rest參数和參数默认值
研究下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參数和參数默认值的更多相关文章
- (一)javascript中的数组index属性——获取数组的索引值
例如:要做到这样的效果 点击每个选项时,会显示不同的div. 我们的做法:在javascript中,先把所有的div的display设置为none,然后在根据当前的数组里的索引值进行一个显示div的过 ...
- js中input文本框设置和移除默认值
这里想实现的效果是:设置和移除文本框默认值,如下图鼠标放到文本框中的时候,灰字消失. 1.可以用简单的方式,就是给input文本框加上onfocus属性,如下代码: <input id=&quo ...
- bootstrapValidator验证的remote中data属性里获取select一直是默认值
budgetEditionNo:{ message:'版本号输入不正确' , validators:{ notEmpty:{ message:'版本号不能为空,请填写' } , remote:{ ur ...
- Apollo 中配置String、Map和List和默认值
摘要:在Apollo 中,配置String.Map和List等类型的信息,同时设置默认值. 综述 随着业务需求的变更,需要在Apollo中配置一个Map<String, List>类型 ...
- javascript中=,==,与===的区别;以及特殊值NaN的讲解
1.在js中"="是作为赋值.var a; a=3:给a赋值为3. 2."=="称作相等,"==="被称作严格相等.当使用"== ...
- javascript中json对象与字符串互转及取值
一. json字符串转换为javascript对象,并取值 var answer = '{"id":0}' var value= JSON.parse(answer); //转 ...
- myeclipse下拷贝的项目,tomcat下部署名称和导出为war包的名称默认值修改
拷贝一个项目,作为一个新的项目,给它换了名字,这时候默认的部署名称等都是原来项目的,这时候要在属性里面修改一下.
- SqlServer中 将某个表的某个字段改个默认值
ALTER TABLE [dbo].[表名] ADD CONSTRAINT [DF_表名_列名] DEFAULT ((默认值)) FOR [列名] ALTER TABLE QA_API ADD CON ...
- JavaScript 中的数据类型
Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...
随机推荐
- 关于platform_device和platform_driver的匹配【转】
转自:http://blog.csdn.net/dfysy/article/details/5959451 版权声明:本文为博主原创文章,未经博主允许不得转载. 说句老实话,我不太喜欢现在Linux ...
- 关于 gstreamer 和 webrtc 的结合,有点小突破
今天让我找到了 gstreamer 的一个牛叉的杀手锏,脑海中马上想到了一个大致的框架和方案计划,用 gst-inspector 先进行对象自省属性探测,然后祭出 gst-launcher 大刀进行管 ...
- hdu 4991(树状数组+DP)
Ordered Subsequence Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- map、hash_map、unordered_map 的思考
#include <map> map<string,int> dict; map是基于红黑树实现的,可以快速查找一个元素是否存在,是关系型容器,能够表达两个数据之间的映射关系. ...
- 无法启动Visual Studio的localhost web服务器,端口"xxxx"已被使用
解决方法:项目属性-Web里面有web服务器端口的设置,换个端口即可.项目属性->web->服务器,不要选择“自动分配端口”,选择“使用指定端口”,后面输入一个端口号
- Wannafly交流赛1 B 硬币[数学思维/贪心]
链接:https://www.nowcoder.com/acm/contest/69/B来源:牛客网 蜥蜴的生日快到了,就在这个月底! 今年,蜥蜴的快乐伙伴之一壁虎想要送好多个1元硬币来恶整蜥蜴. 壁 ...
- usaco-Money Systems
题意: 给出几种硬币,求可用这几种硬币组合出价值为n的方案数.分析: 设dp[i]表示组合出价值i的方案数,则,dp[i]=∑dp[i-val[j]]. #include <iostream&g ...
- Objective-C的self.用法的一些总结
最近有人问我关于什么时候用self.赋值的问题, 我总结了一下, 发出来给大家参考. 有什么问题请大家斧正. 关于什么时间用self. , 其实是和Obj-c的存取方法有关, 不过网上很多人也都这么解 ...
- Unity -- 材质-Material和预设体-Prefabs
材质(Materials)用来把网格(Mesh)或粒子渲染器(Particle Renderers)贴到游戏对象上.他们在定义对象怎么被显示发挥重要组成部分.材质包括用于呈现网状或颗粒着色器的参考,所 ...
- Android 获取虚拟按键的高度
//获取虚拟按键的高度 public static int getNavigationBarHeight(Context context) { int result = 0; if (hasNavBa ...