函数的扩展

1. 函数参数的默认值

优点是简洁,有利于代码优化。
注意:
参数变量是默认声明的,不能使用let和const再次声明,否则会报错。
使用参数默认值时不能有同名参数。
参数默认值是不传值的,每次都重新计算默认值表达式的值
参数默认值的位置:
如果非尾部的参数设置默认值,这个参数是无法省略的,否则会报错。
函数的length属性:
将返回没有指定默认指默认值的参数个数。不包括rest参数
参数的作用域相关:
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域,等到初始化结束这个作用域会消失。这种语法行为在不设置参数默认值时是不会出现的。

2.解构赋值和默认值结合使用

function foo({x,y=5}){
    console.log(x,y);
}
foo({});//undefined 5
foo({x:1});//1 5
foo({x:1,y:2});//1 2
foo();//TypeError:cannot read property 'x' of undefined
/* 只有foo的参数是一个对象时,变量x 和y才会通过解构赋值生成,如果foo调用时函数参数不是对象,变量x和y就不会生成,从而报错。只有参数对象中的y属性值为undefined时,默认值才会生效。*/

注意这两种写法的区别

//写法1
function m1 ({x=0,y=0}={}){
	return [x,y];
}
//写法2
function m2({x,y}={x:0,y:0}){
	return [x,y];
}

上面两种写法都对函数的参数设定了默认值,区别在于写法1参数的默认值是空对象,设置了解构赋值的默认值,写法2函数参数的默认值是一个有具体属性的对象,但是没有设置对象解构赋值的默认值。

2. rest参数

可用来替代arguments对象,更加简单方便
形式:...变量名,变量是一个数组,将多余的参数放入其中。
注意:
rest参数之后不能再有其他参数,否则会报错
ES2016规定,只要函数参数设置了默认值,解构赋值或者扩展远算符,那么函数内部就不能显示的设置为严格模式,否则会报错。
(原因是函数内部的严格模式同时适用于函数体和函数参数,但是函数执行时先执行函数参数,再执行函数体。问题是:只有从函数体中才能知道是否使用严格模式,但是这个时候函数参数已经执行了)

3. name属性

返回改函数的函数名
注意:
匿名函数返回空字符串
Function构造函数返回的私立,name属性值为anonymous
bind返回的函数,name的属性会加上bound前缀

4. 箭头函数

注意:
函数体内的this就是定义的时候所在父级作用域的执行上下文,是固定的。
箭头函数本身没有自己的this,所以他不能够当做构造函数使用,没有new命令
arguments对象在函数体内不存在,可以使用rest参数代替
不可以使用yield命令,因此箭头函数不能用作Generator函数
绑定this:双冒号::(ES7)
左边是一个对象,右边是一个函数,该运算符会自动将左边的对象作为上下文环境绑定到右边的函数上

5. 箭头函数的部署管道机制(pipeline)

cons pipeline = function(...funcs){
	return function (val){//function(5)
		return funcs.reduce(function(a,b){
			return b(a)//参数a初始值为val=5,先执行plus1(5)得到a=6,再执行mult2(6)得到a=12
		},val)
	}
}
const plus1 = function(a){
	return a+1;
}
const mult2 = function(a){
	return a*2;
}
const addThenMult = pipeline(plus1,mult2);
addThenMult(5);
/*执行过程见注释*/

6. 尾调用

是指某一个函数的最后一步操作是调用另外一个函数。
尾调用优化。
调用帧:函数调用会在内存形成一个“调用记录”,又叫调用帧,保存调用位置和内部变量等信息。如果在函数A内部调用函数B,在A的调用帧上方还会形成一个B的调用帧。等到B运行结束将结果返回到A,B的调用帧才会消失。如果函数B内部还调用了函数C,那么就还有一个C的调用帧,以此类推。

7. 尾递归

尾调用自身称为尾递归。对于尾递归来说只存在一个调用帧,永远不会发生“栈溢出”。

8. 函数参数的尾逗号

posted @ 2020-09-29 18:42  小耳朵兔  阅读(191)  评论(0)    收藏  举报