箭头函数

定义

箭头函数是ES6之后增加的一种编写函数的方法,并且它比函数表达式要更加简洁

  • 箭头函数不会绑定this、arguments属性;
  • 箭头函数不能作为构造函数来使用(不能和new一起来使用,会抛出错误);–> (因为箭头函数没有原型);

和普通函数对比

普通函数

1
2
3
4
5
6
7
8
// methods1: function声明
function foo1() { };

// methods2 函数表达式
const foo2 = function (name, age) {
console.log("函数体代码");
console.log(name, age);
};

箭头函数

1
2
3
4
5
//箭头函数的完整写法(和之前 函数表达式 写法类似)
const foo3 = (name, age) => {
console.log("箭头函数函数体代码");
console.log(name, age);
}

箭头函数简写

  1. 如果箭头函数只有一个参数,那么()可以省略
1
2
3
4
5
6
7
8
9
10
const names =["fsllala","fsl","forward"];
const nums =[20,30,45,66,73];

names.forEach(item=>{
console.log(item);
})

const newNums = nums.filter(item=>{
return item%2==0;
})
  1. 如果箭头函数只有一行执行代码,那么{}可以省略
1
2
3
4
5
6
7
const names = ["fsllala", "fsl", "forward"];
const nums = [20, 30, 45, 66, 73];

names.forEach(item => console.log(item))

// 一行执行代码中如果有return关键字,省略{},需要将return一起省略(下一条规则)
const newNums = nums.filter(item => item % 2 == 0)
  1. 只有一行执行代码,这行代码的表达式结果会作为函数的返回值默认返回
1
2
3
4
5
6
7
8
9
10
11
const nums = [20, 30, 45, 66, 73];
const newNums = nums.filter(item => item % 2 == 0);
console.log("newNums",newNums);

// 函数返回值
const arrFn1 =()=>{
return 123;
}
// 简写
const arrFn = ()=>123;
console.log(arrFn()); // 123
  1. 如果默认返回值是一个对象,那么这个对象必须加()
  • 我们先看如下现象,不难发现,当函数的返回值是对象形式的时候,不能区分{}到底是执行体,还是返回的对象
1
2
3
4
5
const arrFn1 = () => 123;  // 函数返回值是个 number
const arrFn2 = () => "fsllala";// 函数返回值是个 string
const arrFn3 = () => [2, 3, 4, 5, 1]; // 函数返回值是个 array
const arrFn4 = () => { name: "fsllala" }; // 函数返回值是个对象
const arrFn5 = ()=>{} //箭头函数执行体
  • 为了区分,这个对象必须加();代表箭头函数的默认返回值是个对象;
1
const arrFn4 = () => ({ name: "fsllala" });

箭头函数this指向

箭头函数不使用this的四种标准规则(也就是不绑定this);箭头函数内部没有绑定自己的this,而是根据外层作用域来决定this;

所以箭头函数中的this和普通变量的查找机制一样,当前作用域没有,会向上层作用域查找;

普通函数没有这个this查找机制,而是遵循this的四种标准规则;详见:this

  1. 全局环境this
1
2
// 直接在全局环境输出this,this指向Window 
console.log("window", this); // Window 
  1. 隐式绑定

绑定改的是函数内部的this指向,但是箭头函数内部没有this,会向上层作用域查找this,但并没有改变上层作用域中的this指向

1
2
3
4
5
6
7
8
9
const foo = () => {
console.log(this);
}
const obj = {
name: "fsllala",
say: foo
}

obj.say(); // Window 
  1. 显示绑定

绑定改的是函数内部的this指向,但是箭头函数内部没有this,会向上层作用域查找this,但并没有改变上层作用域中的this指向

1
2
3
4
5
const foo = () => {
console.log(this);
}
foo(); // Window
foo.call("aaa"); // Window
  1. 箭头函数 例一:
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
26
27
28
29
const obj = {
name: "fsllala",
say: function () {
const bar = () => {
console.log("bar", this);
}
return bar
}
}

const fn = obj.say();
fn(); // {name: 'fsllala', say: ƒ} -->obj对象


/*fn 是箭头函数:
() => {
console.log("bar", this);
}

fn()执行,即为箭头函数执行,箭头函数作用域没有this,会向上层作用域查找,即向:

function () {
const bar = () => {
console.log("bar", this);
}
return bar
}
进行查找,这个是普通函数,有this,this指向是看调用方式了,是隐式调用-->obj.say(),即:this指向的是obj
*/
  1. 箭头函数 例二:

obj是个对象,是没有自己的作用域的;可能有人会说obj是用const声明的,但其实块级作用域形式为{ const xxx=xxxx;}

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
26
27
28
29
const obj = {
name: "fsllala",
say: () => {
const bar = () => {
console.log("bar", this);
}
return bar
}
}

const fn = obj.say();
fn(); //window


/*fn 是箭头函数:
() => {
console.log("bar", this);
}

fn()执行,即为箭头函数执行,箭头函数作用域没有this,会向上层作用域查找,即向:

()=> {
const bar = () => {
console.log("bar", this);
}
return bar
}
进行查找,这个也是箭头函数,没有自己的this,接着向上层作用域查找,即到了全局作用域,全局作用域this指向Window
*/
  1. 箭头函数 例三:

模拟回调函数的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 网络请求的工具函数
function request(url, callbackFn) {
const arrs = ["fsl", "fsllala", 'forward'];
callbackFn(arrs); //回调函数
}

// 实际操作的位置(业务)
const obj = {
names: [],
network: function () {
request("/namesArr", function (params) {
console.log(params); // ["fsl", "fsllala", 'forward']
})
}
}

obj.network();

需求:将回调函数返回的数据添加到obj.names中;

  • methods1:const that = this;
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
26
27
28
// 网络请求的工具函数
function request(url, callbackFn) {
const arrs = ["fsl", "fsllala", 'forward'];
callbackFn(arrs); //回调函数
}

// 实际操作的位置(业务)
const obj = {
names: [],
network: function () {
const that = this;
request("/namesArr", function (params) {
console.log(this); // Window 
that.names = [...params];
})
}
}

obj.network();
console.log(obj);

/*分析:
一:function(params){}中的this 指向:
普通函数,看函数调用; 网络请求的工具函数中callbackFn(arrs)调用的,独立调用,this指向window

二:that.names 中的that; function(params){}没有变量that,向上级作用域找that;上级作用域 const that = this;
即需要查找上级作用域的this,普通函数,看函数调用;obj.network(),所以this指向obj
*/
  • methods2:箭头函数

实际操作的位置(业务)中讲普通函数改为了箭头函数;

1
2
3
4
5
6
7
8
9
10
11
// 实际操作的位置(业务)
const obj = {
names: [],
network: function () {
// 这里改为了箭头函数
request("/namesArr", (params) => {
console.log(this);
this.names = [...params];
})
}
}

整体代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 网络请求的工具函数
function request(url, callbackFn) {
const arrs = ["fsl", "fsllala", 'forward'];
callbackFn(arrs); //回调函数
}

// 实际操作的位置(业务)
const obj = {
names: [],
network: function () {
request("/namesArr", (params) => {
console.log(this); // obj
this.names = [...params];
})
}
}

obj.network();
console.log(obj);
/*分析:
(params)=>{}中的this 指向:
箭头函数,查找上级作用域的this; 上级作用域是普通函数,看函数调用;obj.network(),所以this指向obj
*/