箭头函数与call

在看阮一峰大佬的ES6时,看到一个关于箭头函数和this的例子

1
2
3
4
5
6
7
8
9
10
function foo() {
setTimeout(() => {
console.log('id:', this.id);
}, 100);
}

var id = 21;

foo.call({ id: 42 });
// id: 42

输出结果竟然是42,我一直以为箭头函数的this从函数定义时就已经固定不变了,es6的教程也看过几遍,还是看书不仔细漏过了这个问题

在疑惑后也思考研究了一下,结合搜索到的例子,得出一下结论:
首先不使用箭头函数

1
2
3
4
5
6
7
8
9
10
function foo() {
console.log('this.id:',this.id); // this.id: 42
setTimeout( function () {
console.log('this.id:',this.id); // this.id: 21
},100);
}

var id = 21;

foo.call({ id: 42 });

此时结果都是可以预期的,第一行输出42,是因为call函数改变了foo的指针执行,指向为{id: 42}
第二行输出21,是因为setTimeout是挂载在window下面的。setTimeout实际上又改变了this的指针指向,将this又指向了window。因此输出21。

将函数改为箭头函数

1
2
3
4
5
6
7
8
9
10
function foo() {
console.log('this.id:',this.id); // this.id: 42
setTimeout( () => {
console.log('this.id:',this.id); // this.id: 42
},100);
}

var id = 21;

foo.call({ id: 42 });

此时第一行依旧输出42,这一点是肯定的
分析第二行,箭头函数导致this总是指向函数(箭头函数)定义生效时所在的对象,这句话换个方式理解比较容易理解和记忆,即箭头函数的this指向和将箭头函数的内容拿到函数外层的this指向是一致的
结合上面的例子就是 第二行的this应该和第一行的this是一致的

看到闭包以后,我觉得箭头函数既然没有自己的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
var myObj = {
name : "myObj",
showThis: function(){
console.log(this); // 可以更清晰的看到发生了什么
return () => {
console.log(this.name);
}
}
}
var obj = {
name: "obj"
}

var fnc1 = myObj.showThis()
// {name: 'myObj', showThis: ƒ}
fnc1.call(obj)
fnc1()

var fnc2 = myObj.showThis.call(obj)
// {name: 'obj'}
fnc2()

// myObj
// myObj
// obj

可以看到 call apply 和bind 也无法改变箭头函数的this,始终取决于上层上下文的this