大家都知道普通函数里的this指向最后一个调用他的对象上,箭头函数里的this指向当前作用域的上一个,但是在比较复杂的代码结构中,很多同学在日常工作或面试中总是无法很快判断箭头函数的this指向。
其实我们可以将ES6
中的箭头函数通过Babel
转为ES5
的普通函数来看,就可以发现转义后的箭头函数的this就已经确定,如:
javascript
var b=11;
var obj={
b:22,
say:()=>{
console.log(this.b);
}
}
obj.say(); //输出的值为11
转ES5
后:
javascript
"use strict";
var _this = void 0;
var b = 11;
var obj = {
b: 22,
say: function say() {
console.log(_this.b);
}
};
obj.say(); //输出的值为11
若当前在浏览器环境,则_this
指向window
,那么当下次碰到箭头函数时,我们是否可以往箭头函数的上层作用域找到第一个地方可以写下var _this = this
的语句,那么这里的this
就是这个箭头函数的this
指向。
例子
再看一个复杂一点的例子:
javascript
var str = '111';
const obj = {
str:'obj',
fn: ()=>{
console.log(this.str);
},
fn2: function(){ // fn的上一层是fn2
console.log(this.str)
return {
str: 'newObj',
fn3: ()=>{
console.log(this.str);
}
}
}
}
obj.fn() // 输出 111
obj.fn2().fn3(); //输出obj,obj
笔者在obj
定义了一个箭头函数fn
,在最外层可以定义他的this
,所以fn
的this
指向window
我们在一个返回的对象中定义了一个箭头函数fn3
,在fn3
的上面的fn2
可以定义他的this
,而fn2
是被obj
调用的,所以fn
的this
指向obj
,我们来看一下转为ES5
是怎样:
javascript
"use strict";
var _this = void 0;
var str = '111';
var obj = {
str: 'obj',
fn: function fn() {
console.log(_this.str);
},
fn2: function fn2() {
var _this2 = this;
// fn的上一层是fn2
console.log(this.str);
return {
str: 'newObj',
fn3: function fn3() {
console.log(_this2.str);
}
};
}
};
obj.fn(); // 输出 111
obj.fn2().fn3(); //输出obj,obj
再来看一个例子:
javascript
let object = {
name: "小强",
x: 50,
put() {
setTimeout(
() => {
console.log(this.x);
console.log(this.name);
}, 500);
},
};
object.put(); //输出结果:50 小强
我们直接找到setTimeout
外面的put
函数,在里面写下var _this = this
,把_this
带入箭头函数的this
,就有答案了:
javascript
"use strict";
var object = {
name: "小强",
x: 50,
put: function put() {
var _this = this;
setTimeout(function () {
console.log(_this.x);
console.log(_this.name);
}, 500);
}
};
object.put(); //输出结果:50 小强
箭头函数嵌套箭头函数
当箭头函数里面还有箭头函数时,想象一下把第二个箭头函数的this
定义在fn2
中,那fn2
还是箭头函数,是不是还得往上走,最后把三个箭头函数的this
都定义在fn
中,fn
被obj
调用,所以this
都指向obj
javascript
const obj = {
a: '222',
fn: function () {
return {
fn2: () => {
console.log(this.a) // 222
return () => {
console.log(this.a) // 222
return () => {
console.log(this.a) // 222
}
}
}
}
}
}
obj.fn().fn2()()() // 222 222 222
看看转为ES5
以后:
javascript
"use strict";
var obj = {
a: '222',
fn: function fn() {
var _this = this;
return {
fn2: function fn2() {
console.log(_this.a); // 222
return function () {
console.log(_this.a); // 222
return function () {
console.log(_this.a); // 222
};
};
}
};
}
};
obj.fn().fn2()()(); // 222 222 222
感兴趣的同学可以用在线工具babeljs.io/repl将ES6
转ES5
总结
通过这些例子,大家也能看出来箭头函数的this是在写完代码就已经确定了,而不是运行的时候确定的,希望我的文章能给大家带来一点帮助
欢迎点赞、收藏、转发~