JavaScript函数的多种写法

如果你曾与JavaScript代码打过交道,你应该会很熟悉如何定义和调用函数,但是你真的知道有多少种定义函数的方法吗?对于编写和维护测试Test262(浏览器JavaScript标准测试)来说,这是一个十分常见的挑战,尤其是当一个新特性出现且与现有的函数语法有关联,或者扩展了现有函数的API时。有必要确保新的或被提议的语法和API是有效的,且对语言中的每一个现有变体都是有效的。

本文内容是对JavaScript中已经存在的函数语法格式的概述说明。本文档不包括类声明和表达式,因为这些形式生成的对象不是“可调用的”,对于本文来说,我们只关注生成“可调用的”函数对象的格式。此外,这篇文章也不包括参数列表(包括默认参数、解构,或者尾逗号),因为这些话题足够再写一篇文章了。


大家都知道,最广泛应用也是最早的函数定义形式就是函数声明和函数表达式。前者是最初设计的一部分(1995)并出现在第一个版本的规范(1997年)中,后者是在第三个版本(1999年)引入的。我们可以从这些规范中提取三种不同的定义形式

Function构造器

当我们在讨论一种语言的“函数API”的时候,就已经开始讨论Function构造器。在考虑最初的语言设计时,函数声明的语法形式可以被解释为函数构造器的API的“文字”形式。Function构造器为定义函数提供了一种方法:通过N个字符串参数指定函数参数和函数主体,(如下面的例子)最后一个字符串参数始终是函数主体(需要指出的是,这是一种动态求值形式,会有潜在的安全风险)。对于大多数情况来说,这种形式并不适合,因此它的使用非常稀少——但是自从第一个版本的ECMAScript以来,它就一直存在在JavaScript 中了。

自从ES2015推出以来,已经引入了几种新的语法形式。这些形式的变化是巨大的!

not-so-anonymous函数声明

这是一种新的匿名函数声明形式,如果你曾用过ES Modules,应该清楚这种语法。虽然它可能看起来与匿名函数表达式非常相似,但它实际上有一个默认名称,即“default”

方法定义

对于下面这个例子,大家应该能很快发现它定义了匿名和命名函数表达式作为属性的值。注意,这些不是不同的语法形式。它们是之前讨论过的函数表达式的示例,是在初始对象时编写的。这种形式最初是在ES3中引入的。

箭头函数

作为ES2015最具争议性的函数之一,箭头函数已经变得众所周知且无处不在。箭头函数语法是这样定义的,它为函数声明提供了两种不同的格式:赋值表达式(箭头后面没有跟“{”大括号时为赋值表达式)和函数体(代码中包括0到多个语句时为函数体)。这个语法还允许在描述单个参数时不加圆括号,然而0个或一个以上参数需要加圆括号。这些语法结构允许箭头函数拥有多种书写形式:

未被括起来的形式——也就是没有圆括号的形式——即在箭头函数只能表现为只用一个标识符名称作为参数的形式。当箭头函数在异步函数或生成器中定义时,这个标识符名称需要以await或yeild作为前缀定义。但这是我们在箭头函数中能得到的最大程度的不用括号括起来参数列表的情况。

箭头函数可以(也经常)出现在初始化值或属性定义的赋值中,上面所示的箭头函数表达式已经包括了这种情况

生成器

生成器有一种特殊的语法,除了箭头函数和定义setter / getter方法的时候不能添加之外,可以被添加在其他所有语法形式中。我们可以用其生成函数声明、表达式、定义,甚至构造函数。

ES2017

异步函数

经历了几年的发展,异步函数将于2017年6月发布ES2017的EcmaScript语言规范的第8版引入。尽管如此,许多开发人员已经使用了这个特性,这要归功于Babel的早期实现支持!

Async函数语法为描述异步操作提供了一种干净而统一的方式。调用时,Async函数对象将返回一个Promise对象,这个对象将在异步函数返回时被解析。当包含一个await表达式时,异步函数可能暂停函数的执行,然后将其用作异步函数的返回值

继续更新的ES2017

异步生成器 Async Generators

在接下来的ES017中,async和await关键字将被扩展以支持新的异步生成器形式。这个特性的进展可以通过proposal’s github repository进行跟踪。您可能已经猜到,这是async、await和现有的生成器声明和生成器表达式语法的组合。调用时,异步生成器返回一个迭代器,它的next()方法返回Promise对象然后用迭代器对象解析,而不是直接返回迭代器对象。

可以在许多地方发现异步生成器,你可能已经生成器函数中见到它了。

复杂的挑战

每个函数语法格式不仅对学习和使用是挑战,而且对JS运行时间和Test262的实现和维护也是一个挑战。当引入新的语法形式时,Test262必须与所有相关的语法规则一起测试该新形式。例如,将默认参数语法的测试形式限制在简单的函数声明形式中,并假设在其他格式下该语法也正常起作用是不明智的。每一个语法规则都必须经过测试,将这些测试任务分配给一个人是不合理的。所以导致了测试生成工具的设计和实现。测试生成工具提供了一种确保能够覆盖(函数格式的多少)更详尽的方法。

这个项目现在包含了一系列由不同的测试用例和模板组成的源文件,例如,如何检查每个函数格式的参数,或者函数格式测试,甚至更多超出范围的函数形式,在这些函数形式中,解构绑定和解构赋值都是适用的。

尽管它可能导致密集的和长时间的发送请求,但是覆盖率总是会提高,而且可能总是会发现新的错误。

为什么了解所有的函数格式是很重要的?

如果不需要在Test262上编写测试,计算和列出所有函数表单可能并不重要。这里已经列出了许多格式的模板。新的测试可以很容易地使用现有的模板作为起点。

确保EcmaScript规范的良好测试是Test262的主要任务。这对所有的JavaScript运行时间都有直接的影响,我们识别的格式越多,覆盖率就越全面,这将帮助新功能更无缝地集成,不管您使用的平台是什么。

你可能感兴趣的:(JavaScript函数的多种写法)