ES6 函数的扩展
函数参数的默认值
基本用法
在ES6之前,不能直接为函数的参数指定默认值,如其中某个参数不传或者类型不符合,产生的结果也是意想不到的。比如下面一个除法函数,第二个参数不传或者我们传递一个字符串:
为了避免这个问题,通常需要先判断一下参数y
是否被赋值,如果没有,做另外的处理。针对上面的例子,做如下的调整
在ES6中允许为函数的参数设置默认值,即直接写在参数定义的后面。改造上面的例子,这样第一个console.log就可以打印出值了。
从上面的例子可以看到ES6的写法比ES5简洁许多,而且非常自然。
除了简洁,ES6的写法还有两个好处:首先,阅读代码的人,可以立刻意识到哪些参数是可以省略的,不用查看函数体或文档;其次,有利于将来的代码优化,即使未来的版本在对外接口中,彻底拿掉这个参数,也不会导致以前的代码无法运行。
注意
因为参数变量在函数上是默认声明的,所以不能用let
或const
再次声明了,否则会出现错误。
上面代码中,参数变量x
是默认声明的,在函数体中,不能用let
或const
再次声明,否则会报错。
与解构赋值默认值结合使用
参数默认值可以与解构赋值的默认值,结合起来使用。看下面的例子
上面代码中,如果函数setOption
的参数对象设置了method和dataType属性,那么就采用设置的,否则采用默认的。
温馨提示
这里需要注意的是解构的对象必须放在最后面。
参数默认值的位置
通常情况下,定义了默认值的参数,应该是函数的尾参数。因为这样比较容易看出来,到底省略了哪些参数。如果非尾部的参数设置默认值,实际上这个参数是没法省略的。来看下面的一个例子:求三个数的和。
上面代码中,sum函数的默认值参数都不是尾参数。这时,无法只省略x,y参数了,否则算出来的结果就不正确了。相反的。sum1函数的默认值参数是最后的。所以15行,16行,17行可以输出正确的结果。
函数的length属性
指定了默认值以后,函数的length
属性,将返回没有指定默认值的参数个数。也就是说,指定了默认值后,length
属性将失真。
上面代码中,length
属性的返回值,等于函数的参数个数减去指定了默认值的参数个数。比如,obj1,定义了1个参数,但是给其指定了默认值,因此length
属性等于0。
这是因为length
属性的含义是,该函数预期传入的参数个数。某个参数指定默认值以后,预期传入的参数个数就不包括这个参数了。同理,rest参数也不会计入length
属性。
(function(...args) {}).length // 0
我们来看一下默认值不是最后一个参数的现象:
结论
如果设置了默认值的参数不是尾参数,那么length
属性也不再计入后面的参数了。
作用域
一个需要注意的地方是,如果参数默认值是一个变量,则该变量所处的作用域,与其他变量的作用域规则是一样的,即先是当前函数的作用域,然后才是全局作用域。
上面代码中,参数y
的默认值等于x
。调用时,由于函数作用域内部的变量x
已经生成,所以y
等于参数x
,而不是声明的let x
这个变量。
如果调用时,函数作用域内部的变量x没有生成,结果就会不一
样。
上面例子中,函数调用时,y
的默认值变量x
尚未在函数内部生成,所以x
指向全局变量。
如果此时,全局变量x
不存在,就会报错。
应用
利用参数默认值,可以指定某一个参数不得省略,
如果省略就抛出一个错误。
上面例子中的fun函数,如果调用的时候没有参数,就会调用默认值throwException
函数,从而抛出一个错误。
从上面代码还可以看到,参数x
的默认值等于throwException
函数的运行结果(即函数名之后有一对圆括号),这表明参数的默认值不是在定义时执行,而是在运行时执行(即如果参数已经赋值,默认值中的函数就不会运行),这与python语言不一样。
另外,可以将参数默认值设为undefined
,表明这个参数是可以省略的。
如果是确实想省略这个参数可以给参数设置undefined默认值
rest参数
ES6引入rest参数(形式为“...变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
上面代码的sum函数是一个求和函数,利用rest参数,可以向该函数传入任意数目的参数。
注意
rest参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。
扩展运算符
含义
扩展运算符(spread)是三个点(...
)。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。
我们见的比较多的都是在前端项目中,比如下面的例子
将两个数组合并成一个数组。
由于扩展运算符可以展开数组,所以不再需要apply
方法,将数
合并数组
参见上面的例子
函数的返回值
JavaScript的函数只能返回一个值,如果需要返回多个值,只能返回数组或对象。扩展运算符提供了解决这个问题的一种变通方法。
字符串
扩展运算符还可以将字符串转为真正的数组。
这样如果我们需要查找字符串中某个字符出现的位置,可以通过这种方式先转换成数组,然后再去处理。
箭头函数
基本用法
ES6允许使用“箭头”(=>
)定义函数。
var f = v => v;
上面的箭头函数等同于:
var f = function(v) {
return v;
};
如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。
如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return
语句返回。
由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号。