【AICon】探索RAG 技术在实际应用中遇到的挑战及应对策略!AICon精华内容已上线73%>>> 了解详情
写点什么

深入浅出 ES6(五):不定参数和默认参数

  • 2015-07-06
  • 本文字数:2618 字

    阅读完需:约 9 分钟

编者按:ECMAScript 6 已经正式发布了,作为它最重要的方言,Javascript 也即将迎来语法上的重大变革,InfoQ 特开设“深入浅出ES6 ”专栏,来看一下ES6 将给我们带来哪些新内容。本专栏文章来自 Mozilla Web 开发者博客,由作者授权翻译并发布。

今天这篇文章将为你带来两个使 JavaScript 函数语法更富表现力的新特性:不定参数和默认参数。

不定参数

我们通常使用可变参函数来构造 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 来给不定参数默认参数使用。

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

文后盘点

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

鸣谢:感谢 Benjamin Peterson 在 Firefox 中实现了这些特性,同时感谢他对于整个项目的贡献,以及他用心撰写了本篇文章。

在下一篇文章中,我们将介绍另外一个简单、优雅、实用,同样是你每天都会用到的 ES6 特性。这篇文章中用到了你平时用来写数组和对象的熟悉的语法,并为这些语法润色,产生一个新的、简洁的方式来拆解数组和对象。那意味着什么呢?为什么要拆解对象?敬请期待 Mozilla 工程师 Nick Fitzgerald 为我们带来的《深入浅出 ES6 解构》。

2015-07-06 07:1651560
用户头像

发布了 63 篇内容, 共 131.6 次阅读, 收获喜欢 38 次。

关注

评论

发布
暂无评论
发现更多内容

阿里十年架构师总结的Java核心知识点大全,恐怖程度难以想象!

开心学Java

Java spring JVM Java工程师 多线程并发

架构实战营第10期毕业设计-秒杀系统

Geek_4db2d5

媒体赞誉丨九科信息入选“第一新声”2022高成长新锐企业榜、RPA高成长企业榜,并受邀参加“2022年高科技高成长年度峰会”

九科Ninetech

面试处处碰壁?不慌,Java核心面试文档.PDF助你披荆斩棘

三十而立

综合系统清理优化工具:MacCleaner PRO中文激活版

真大的脸盆

Mac Mac 软件 mac系统清理优化软件 清理工具 清理优化

「Go框架」bind函数:gin框架中是如何绑定请求数据的?

Go学堂

golang 开源 程序员 个人成长

Java并发夺命23问

程序员大彬

Java Java并发 java面试

App Store 新定价机制 - 2023年最全版

37手游iOS技术运营团队

ios iap In App Purchase App Store Connect API app store

户外广告屏为什么会坏?

Dylan

LED 户外LED显示屏

机器学习算法(一): 基于逻辑回归的分类预测

汀丶人工智能

数据挖掘 机器学习 数据分析 逻辑回归

谷歌架构师分享gRPC与云原生应用开发Go和Java为例文档

程序知音

Java 架构 云原生 编程语言 后端

Java程序员涨薪必备的性能调优知识点,收好了

三十而立

Java

《动手学深度学习--PyTorch》之学习环境搭建

IT蜗壳-Tango

GPT-4免费无限制使用教程

南城FE

人工智能 AI 前端 ChatGPT

PyTorch 深度学习实战 | 基于ResNet的花卉图片分类

TiAmo

数据集 PyTorch

"我眼中的ChatGPT"征文获奖作品合集

InfoQ写作社区官方

技术专题合集 热门活动 ChatGPT

9 个可以快速掌握的 Java 性能调优技巧,必须掌握

三十而立

Java

得物社区计数系统设计与实现

得物技术

性能优化 重构 稳定性

硬核!阿里出品2023版Java架构师面试指南,涵盖Java所有核心技能

三十而立

Java java面试

利用 Amazon Managed Blockchain 发展和扩大忠诚度奖励计划(第一部分)

亚马逊云科技 (Amazon Web Services)

人工智能

AIGC导航网站推荐

kcodez

人工智能 AIGC Chat ChatGPT

云原生引擎单元测试实践

京东科技开发者

云原生 单元测试 代码覆盖

三月征文活动结果已出炉,快来看看有没有你

InfoQ写作社区官方

热门活动 ChatGPT

Removing HTTP/2 Server Push from Chrome

Yestodorrow

一种基于实时大数据的图指标解决方案

京东科技开发者

大数据 运维 系统架构 开发 图指标

【程序员日记】---当“微服务”遇到了“电饼铛“

京东科技开发者

架构 微服务 系统架构 开发 企业号 3 月 PK 榜

如何构建内部开发者门户:企业参考指南

SEAL安全

企业号 3 月 PK 榜 开发者体验 内部开发者门户

SaaS时代下的我们需要什么样的数据库?

陈飞

架构实战营10期-模块九作业

炮仗

SVN管理工具:Cornerstone 4 激活版

真大的脸盆

svn Mac Mac 软件 SVN客户端

场景重塑:乐播投屏搭载无影架构,打造“超级投屏空间”

云布道师

无影

深入浅出ES6(五):不定参数和默认参数_JavaScript_Benjamin Peterson_InfoQ精选文章