ES6之函数的扩展
函数参数的默认值
基本用法
es6之前函数的参数不能使用默认值,只能采取这种写法:
1 | function a(x){ |
但是es6可以为函数的参数设置默认值:
1 | function a(x = 1){ |
不能有重复参数:
非严格模式下,重复参数不会报错:
1 | function a(x, x, y) { |
但是严格模式或者使用参数默认值时,不能使用这种写法:
1 |
|
参数变量是默认声明的
不能再次使用let或者const声明和参数相同的变量:
1 | function foo(x = 5) { |
函数参数默认值时惰性求值
下面代码中的p的默认值是x+1,每次调用都会重新计算x+1的值:
1 | let x = 99; |
与解构赋值默认值结合使用
基本用法
1 | function foo({x, y = 5}) { |
下面两种写法的结果是相同的,但是执行过程确不同:
- 写法一:默认值为
{},结构赋值的默认值为x=0 y=0 - 写法二:默认值为
{x:0,y:0},结构赋值之后x=0 y=0
1 | // 写法一 |
参数默认值的位置
通常情况下,定义了默认值的参数应该是函数的尾参数,因为前面的参数无法省略,触发你你显示的传入undefined
1 | function a(a=1,b){ |
函数参数的length属性
指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数。也就是说,指定了默认值后,length属性将失真。
并且函数的length属性会忽略第一个有默认值的参数后面所有的参数。
1 | (function (a) {}).length // 1 |
作用域
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。
1 | var x = 1; |
调用函数f时,参数形成一个单独的作用域。在这个作用域里面,默认值变量x指向第一个参数x,而不是全局变量x,所以输出是2。
rest 参数
基本用法
ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
1 | function add(...values) { |
rest和arguments的区别
arguments是一个类数组对象,而rest参数是一个真正的数组。
- arguments想要调用数组的方法要这样
Array.prototype.slice.call(arguments).sort() - 它们都有length属性,返回参数数量
- 函数的length属性不包括rest参数
1 | function a(...values) { |
严格模式
从 ES5 开始,函数内部可以设定为严格模式。
但是在ES6中只要参数使用了默认值、解构赋值、或者扩展运算符,就不能显式指定严格模式。
name属性
函数的name属性,返回该函数的函数名。这个属性早就被浏览器广泛支持,但是直到 ES6,才将其写入了标准。
1 | function foo() {} |
ES6 对这个属性的行为做出了一些修改。如果将一个匿名函数赋值给一个变量,ES5 的name属性,会返回空字符串,而 ES6 的name属性会返回实际的函数名。
1 | var f = function () {}; |
Function构造函数返回的函数实例,name属性的值为anonymous。
1 | (new Function).name // "anonymous" |
bind返回的函数,name属性值会加上bound前缀。
1 | function foo() {}; |
箭头函数
箭头函数的使用方法就不说了。。。
使用注意点
关于箭头函数的this的绑定问题,可以看我这篇博文JavaScript中的this
- 函数体内的
this对象,就是定义时所在的对象,而不是使用时所在的对象。 - 不可以当作构造函数,也就是说,不可以使用
new命令,否则会抛出一个错误。 - 不可以使用
arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。 - 不可以使用
yield命令,因此箭头函数不能用作 Generator 函数。
不适用场合
第一个场合是定义对象的方法,且该方法内部包括this。
1 | const cat = { |
这里的箭头函数指向全局,而不是指向cat。
第二个场合是需要动态this的时候,也不应使用箭头函数。
1 | var button = document.getElementById('press'); |
这里的this指向的也是全局而不是button对象。
其它改动
函数参数的尾逗号
ES2017 允许函数的最后一个参数有尾逗号(trailing comma)。这样的规定也使得,函数参数与数组和对象的尾逗号规则,保持一致了。
Function.prototype.toString()
ES2019 对函数实例的toString()方法做出了修改,以前会省略注释和空格,修改后的toString()方法,明确要求返回一模一样的原始代码。
1 | function /* foo comment */ foo () {} |
catch 命令的参数省略
JavaScript 语言的try...catch结构,以前明确要求catch命令后面必须跟参数,接受try代码块抛出的错误对象。
很多时候,catch代码块可能用不到这个参数。但是,为了保证语法正确,还是必须写。ES2019 做出了改变,允许catch语句省略参数。
1 | try { |
ps: 如何在typescript中使用rest参数?定一个any[] 吗?这样岂不是违反了使用ts的初衷,可读性和可维护性变差了?