函数的扩展
1.函数参数的默认值
1.1 参数变量是默认声明的,不能用let或者const再次声明
使用参数的默认值时,函数不能有同名参数
参数默认值是不传值的,而是每次都重新计算默认值表达式的值。(参数默认值是惰性求值的)
let x = 99;
function foo(p = x + 1) {
console.log(p);
}
foo() // 100
x = 100;
foo() // 101
上面代码中,参数p的默认值是x + 1。这时,每次调用函数foo(),都会重新计算x + 1,而不是默认p等于 100
1.2参数默认值与解构赋值的默认值结合使用,函数参数的默认值生效以后,参数解构赋值依然会进行
1.3参数默认值的位置
定义默认值的参数,应该是函数的尾参数,这样可以比较容易看出来到底省略了哪写参数
1.4函数的length属性
指定了默认值以后,函数的length属性就是返回没有指定默认值的参数个数,若是指定了默认值后,length属性将会失真
length属性的含义是该函数预期传入的参数个数,某个参数指定默认值以后,预期传入的参数个数就不包括这个参数,rest参数也不会计入length属性
如果设置了默认值的参数不是尾参数,那么length属性不再计入后面的参数
1.5 作用域
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域
利用参数默认值可以指定某个参数不得省略,如果省略就抛出一个错误
如果参数已经赋值,默认值中的函数就不会运行,若将参数默认值设为undefined,表明这个参数是可以省略的
2.rest参数
rest参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了
rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中
arguments对象不是数组,而是一个类似数组的对象,所以为了使用数组的方法必须使用Array.from先将其转为数组
// arguments变量的写法
function sortNumbers() { return Array.from(arguments).sort(); }
// rest参数的写法
const sortNumbers = (...numbers) => numbers.sort();
rest参数之后不能再有其他参数(即只能是最侯一个参数),否则会报错 函数的length属性,不包括rest参数
3.严格模式 'use strict'
只要函数参数使用了默认值,解构赋值,或者扩展运算符,那么函数内部就不能显示设定为严格模式,否者会报错
规避限制的方法
1.设定全局性的严格模式
'use strict'; function doSomething(a, b = a) { // code }
2.把函数包在一个无参数的立即执行函数里面
const doSomething = (function () { 'use strict'; return function(value = 42) { return value; }; }());
4.name属性
函数的name属性,返回该函数的函数名
如果匿名函数,ES5和ES6的name属性返回的值不一样
如果将一个具名函数赋值给一个变量,ES5和ES6的name属性都会返回这个具名函数原本的名字
Function构造函数返回的函数实例,name属性的值为anonymous
bind返回的函数,name属性值会加上bound前缀
5.箭头函数
允许箭头(=>)定义函数 如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分
如果箭头函数的代码块部分多余一条语句,就要使用大括号将它们括起来,并且使用return语句返回 由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错
如果箭头函数只有一行语句,且不需要返回值,可以采用下面的写法,就不用写大括号了。
let fn = () => void doesNotReturn();
箭头函数可以与变量解构结合使用。
箭头函数的一个用处是简化回调函数。
// 普通函数写法
[1,2,3].map(function (x) { return x * x; });
// 箭头函数写法
[1,2,3].map(x => x * x);
【注】
1.箭头函数没有自己的this对象
2.不可以当作构造函数,也就是说不可以对箭头函数使用new命令,否则会抛出一个错误
3.不可以使用arguments对象,该对象在函数题内不存在,如果要用,可以用rest参数替代
4.不可以使用yield命令,因为箭头函数不能用作Generator函数
不适用场合:
1.定义对象的方法,且该方法内部包括
this const cat = { lives: 9, jumps: () => { this.lives--; } }
如果写成上面那样的箭头函数,使得this指向全局对象,因此不会得到预期结果。这是因为对象不构成单独的作用域,导致jumps箭头函数定义时的作用域就是全局作用域。
2.需要动态的this的时候,也不应该使用箭头函数