函数的扩展
目录1. 函数的默认值
-
ES6允许直接在函数的形参中设置默认值
function Point(x = 0,y = 0){ let x; //不允许重复声明 this.x = x; this.y = y; } var p = new Point(); p; //{x:0,y:0}
-
注意:
- 参数变量是默认声明的,即不能用let或const再次声明
- 参数默认值不是传值的,而是每次都重新计算默认值表达式的值
1.1 解构赋值默认值与函数默认值
-
解构赋值默认值与函数默认值可以组合使用,但两者常常难以区分
- 解构赋值默认值通常处于"内层",即对象/数组内部
- 函数默认值通常处于"外层",即在小括号内部的最外层
//写法1:既设置了函数默认值"xxx={}",又设置了解构赋值默认值"{x=0,y=0}" function m1({x=0,y=0}={}){ return [x,y]; } //写法2:只设置了函数默认值"xxx={x:0,y:0}",没有设置解构赋值默认值 function m2({x,y} = {x:0,y:0}){ return [x,y]; }
-
连锁触发
function fetch(url,{method = 'GET'} = {}){ console.log(method); } fetch("www.baidu.com",{}); //"GET" fetch("www.baidu.com"); //"GET"
解析:
这里同时使用了解构赋值默认值与函数默认值
如果传递第二个参数,则按照解构赋值默认值的特性,会获得method="GET"
但如果不传递第二个参数,解构赋值默认值就不会被触发,此时函数赋值默认值就可以弥补这一点,当函数赋值默认值为{}时,就又触发了解构赋值默认值,这样就又有method="GET"
1.2 参数默认值的位置
-
带默认值的参数一般都写于尾部,否则无法直接省略该参数
function f(x = 1 , y){ return [x,y]; } f(); //[1,undefined] f(2); //[2,undefined] f(,1); //报错 f(undefined,1); //[1,1] //可以看到,除非显式声明undefined,否则无法跳过x为y赋值
2. rest参数
-
ES6引入了rest参数,用于获取函数的多余参数,这个参数一定程度上替代了arguments
rest参数搭配的变量是一个数组,该变量将多余的参数放入其中,同时由于本质上是一个数组,所以所有数组具有的方法也可以应用于rest参数
function add(...values){ let sum = 0; for(var val of values){ sum += val; } return sum; } add(2.5,3); //10
-
注意:
- rest参数必须是最后一个形参,否则会报错
- rest函数与扩展运算符
...[对象]
书写方法相似,注意区分。一般来说rest函数只会出现于等号的左边,即被赋值方(形参);而扩展运算符只会出现于等号的右边,即赋值方(实参)
3. 箭头函数
3.1 基础用法
-
ES6允许使用箭头
=>
定义函数,箭头的左边为形参,右边为return值(或代码块)var f = v => v; //对应 var f = function(v){ return v; };
var f = () => 5; //对应 var f = function(){ return 5; };
var sum = (num1,num2) => num1+num2; //对应 var sum = function(num1,num2){ return num1 + num2; };
-
如果箭头函数的代码块部分多于一条语句,需要使用大括号将其括起来
var sum = (num1,num2) => {return num1 + num2;}
-
由于大括号被解释为代码块,所以若箭头函数直接返回对象,必须在对象外面加上小括号
var getTempItem = id => ({id:id, name:"Temp"});
3.2 箭头函数中的this
-
箭头函数有以下几个注意事项:
- 函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象
- 不可以当作构造函数,即不可使用new命令,否则会报错
- 不可以使用arguments对象,该对象在函数体内不存在,如果有需要可以使用rest参数代替
- 不可以使用yield命令,因此箭头函数不能用作Generator函数
-
其中最值得注意的一点就是箭头函数中this的指向:
- this对象的指向是可变的,但在箭头函数中它是固定的
- 箭头函数会让函数中的this绑定定义时所在的作用域,而不是指向运行时所在的作用域
- this指向的固定化并不是因为箭头函数内部有绑定this的机制,而是因为箭头函数根本没有自己的this
- 由于没有this,也就不能用call(),apply(),bind()这些方法去改变this的指向
-
为了方便理解,下面给出差分实例
普通对象方法
这里的function作为obj1对象的方法出现,this指向obj1的对象本身
var obj1 = { firstName: "Jackey", lastName: "Chen", getFullName: function(){ console.log(this); return this.firstName + this.lastName; } } console.log(obj1.getFullName()); //JacktyChen
带有函数的对象方法
此处在方法中又添加了一个函数,由于函数执行的本质是window.[函数名],所以调用者就变成了window
而window本身并不具有firstName和lastName,所以输出NaN
var obj2 = { firstName: "Jackey", lastName: "Chen", getFullName: function(){ var fn = function(){ console.log(this); return this.firstName + this.lastName; } return fn(); } } console.log(obj2.getFullName()); //NaN
带有箭头函数的对象方法
此处将方法中的函数替换成了箭头函数,由于箭头函数本身不具有this,它会向上一级寻找this,所以this就是obj3,可以正常调用
var obj3 = { firstName: "Jackey", lastName: "Chen", getFullName: function(){ var fn = () => { console.log(this); return this.firstName + this.lastName; } return fn(); } } console.log(obj3.getFullName());
3.3 用途
-
简化代码
- map函数
//正常写法 [1,2,3].map(function(x){ return x*x; }); //箭头函数 [1,2,3].map(x => x*x);
- sort函数
//正常写法 var result = values.sort(function(a,b){ return a - b; }); //箭头函数 var result = values.sort((a,b) => a-b);
-
封装回调函数
var handler = { id:'123456', init:function(){ document.addEventListener('click',event=>this.doSth(event.type),false); }, doSth:function(type){ console.log('Handling' + type + 'for' + this.id); } };
解析:
init
方法使用到了对象内的doSth
方法,但是doSth
方法又使用到了this如果单独使用
doSth
方法是不会有任何问题的,因为在调用方法的时候this默认是指对象本身但是在
init
内,doSth
是作为回调函数出现的,也就是说它的this指向的是function的上级,即window所以此处需要使用箭头函数,由于箭头函数没有自己的this,所以默认调用上一级的this,即
init
中的this,此时this便又指向了对象本身
查漏补缺:函数设置默认值后的length属性,函数设置默认值后的作用域,严格模式,name属性,绑定this
标签:function,ES6,return,函数,箭头,函数参数,var,默认值 From: https://www.cnblogs.com/Solitary-Rhyme/p/16954756.html