箭头函数看这篇就够了

初试箭头函数

作用:函数目的指向性更强,可读性更好,简化代码,提高开发效率

特点:

代码1:

1
2
3
4
5
6
let add = (a, b) => {
return a + b;
}

//也可以这样写,省略return更加简洁
let add = (a,b)=>(a+b);

代码2:

1
2
3
4
5
6
7
8
//对象的应用
let func1 = (a,b,c)=>({a,b,c});
let func2 = (a,b,c)=>({aa:a,bb:b,cc:c});
// let func3 = (a,b,c)=>{aa:a,bb:b,cc:c};//如果不加圆括号是会报错的

console.log(func1(12,35,5));
console.log(func2(12,35,5));
// console.log(func3(12,35,5));

代码3:

箭头函数必须用一个东西来存,可以使变量、属性或者使数组,想比于ES5中函数可以用function funC(a,b){}格式声明,箭头函数是不允许的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//用变量存
let sum = () => {

};
sum();//这样调用

//用对象属性存
let obj = {
fn: () => {

}
}
obj.fn();//这样调用

//用数组存
let arr = [() => {}];
arr[0]();//这样调用

高阶函数应用

数学和计算机科学中,高阶函数是至少满足下列一个条件的函数: 接受一个或多个函数作为输入参数,返回输出一个函数

箭头函数在高阶函数的应用中可以使代码更加简便,下面来看一下对比:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//高阶函数之ES5的传统方法

function sum(x){
return function(y){
return function (z) {
return x+y+z;
}
}
}

var sum1 = sum(1);
var sum2 = sum1(2);
var sum3 = sum2(3);
console.log(sum3);//成功输出6
/*************把上面的函数改成箭头函数语法**********************/
let sum = (x)=>{
return (y)=>{
return (z)=>{
return x+y+z;
}
}
}
/*************进一步省略return**********************/
let sum = (x)=>(y)=>(z)=>(x+y+z);
console.log(sum(1)(2)(3));//输出6

arguments

内部arguments和this都是由定义时外围最接近一层的非箭头函数的arguments和this决定其值的

1
2
3
4
5
6
7
8
9
10
// 举个例子
var myfun1 = function(a,b){
console.log(arguments,a,b);
}
myfun1(12,5);//可以正常输出arguments和12和5

let myfun2 = (a, b) => {
console.log(arguments, a, b)
}
myfun2(12, 5);//报错,arguments未定义,myfun2函数外围没有非箭头函数

再举个带外围非箭头函数的例子:

1
2
3
4
5
6
7
8
9
function test(){
let myfun2 = (a, b) => {
console.log(arguments, a, b)
}
console.log('我是箭头函数的外围非箭头函数test');
myfun2(1,2);
}

test(12,5,6);

再说另一个应用场景:

1
2
3
4
5
6
7
8
//ES5中获取外围最近函数的arguments的做法
function Curry() {
var arg = arguments;
return function () {
console.log(arg, arguments);
}
}
Curry('a', 'b')(11, 22);
1
2
3
4
5
6
7
//ES5中获取外围最近函数的arguments的做法
function Curry() {
return ()=> {
console.log(arguments);
}
}
Curry('a', 'b')(1,2);

this

内部arguments和this都是由定义时外围最接近一层的非箭头函数的arguments和this决定其值的

不过有一点不同,对于arguments如果外围没有非箭头函数,使用时是报错,提示arguments未定义;

而this如果外围没有非箭头函数,使用时不会报错,规定其值为window

1
2
3
4
let sum = () =>{
console.log(this);
}
sum();//打印结果为window对象

例子:

1
2
3
4
5
6
7
8
9
10
11
//之所以用var定义a是为了把a挂载到window上
var a = 'outer';

let obj = {
a: 'inner',
fn: () =>{
console.log(this.a); // 该箭头函数没有外围非箭头函数,this指向window
}
}

obj.fn();//如果安装ES5的写法结果时inner,但是结果是outer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//之所以用var定义a是为了把a挂载到window上
var a = 'outer';

let obj = {
a: 'inner',
fn(){
test=()=>{
console.log(this.a); //此时this指向了fn的this也就是obj对象
};
return test;
}
}

obj.fn()();//结果为inner

比较实际的一个应用setTimeout:

setTimeout是window对象里的一个方法,其this是指向window的

1
2
3
4
5
6
7
8
9
let myObj = {
ms: 'hhhhh',
fn(){
setTimeout(function(){
console.log(this.ms)
}, 500);
}
};
myObj.fn();//输出结果为undefined而非我们想要的hhhhh,因为setTimeout指向的this是window
1
2
3
4
5
6
7
8
9
10
11
//针对上述情况的解决方法
let myObj = {
ms: 'hhhhh',
fn(){
let that = this;//把fn的this赋给that,that此时指向fn的对象myObj
setTimeout(function(){
console.log(that.ms)
}, 500);
}
};
myObj.fn();//成功输出hhhhh,但是这样太麻烦了,事实上这样的写法就是ES6代码babel后的ES5写法
1
2
3
4
5
6
7
8
9
10
//用箭头函数直接搞定
let myObj = {
ms: 'hhhhh',
fn(){
setTimeout(() => {
console.log(this.a)
}, 500);
}
};
myObj.fn();//成功输出hhhhh,利用了箭头函数this为外围非箭头函数fn的this