Stevv's Blog

Do not go gentle into that good night

箭头函数和this关键字

箭头函数,多数时候像函数表达式的简写语法。最重要的区别是箭头函数没有和 this 关键字绑定。

对一个函数表达式来说,this 会随着函数调用时的上下文改变。而箭头函数,this 会基于词法作用域。箭头函数遵循普通变量的寻找方式,先在当前作用域中查找 this ,若没有找到则会继续寻找上一层作用域。

直接调用

1
2
3
4
5
const foo = () => {
return this;
}

console.log(foo()); // window or global object

完全与函数表达式相同。

作为构造函数

1
2
3
4
5
6
7
8
9
10
11
const Order = (main, side, dessert) => {
this.main = main;
this.side = side;
this.dessert = dessert;
this.order = function () {
return `I will have ${this.main} with ${this.side} and finish off with a ${this.dessert}`;
}
}
const newOrder = new Order("sushi", "soup", "yogurt"); // Order is not a constructor

console.log(newOrder.order());

箭头函数不能用作构造器。在这个例子中他们表现的不同,虽然将this.order 改为箭头函数,但如果我们不使用箭头函数作为构造函数,效果也是一样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
function Order(main, side, dessert) {
this.main = main;
this.side = side;
this.dessert = dessert;
this.order = () => {
return `I will have ${ this.main } with ${ this.side } and finish off with a ${ this.dessert } `;
}
}
const newOrder = new Order("sushi", "soup", "yogurt");

console.log(newOrder.order());
// I will have sushi with soup and finish off with a yogurt

作为对象方法调用

1
2
3
4
5
6
7
8
9
10
11
const myObject = {
main: "butter chicken",
side: "rice",
dessert: "ice cream",
order: () => {
return `I will have ${this.main} with ${this.side} and finish off with ${this.dessert}`;
}
}

console.log(myObject.order());
// I will have undefined with undefined and finish off with undefined

与函数表达式表现的不同, 作为对象方法时箭头函数不能直接替换函数表达式。

在严格模式下使用

1
2
3
4
5
6
7
"use strict";
const foo = () => {
return this;
};

console.log(foo() === undefined); // false
console.log(foo()); // window or global object

与函数表达式表现不同,因为词法作用域中的 this 优先与严格模式下的 this 规则。

在事件中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html lang="en">
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
</head>
<body>
<button id="mybutton">
Click me!
</button>
<script>
var element = document.querySelector("#mybutton");
element.addEventListener('click', (event) => {
console.log(this); // window object
console.log(this.id); // undefined
}, false);
</script>
</body>
</html>

与函数表达式表现不同,箭头函数中的 this 是根据定义它的位置决定的,而不是它使用的地方。在这个例子中,我们可以使用 event.currentTarget 来获取元素。

总结:除了自身直接使用,箭头函数表现的与函数表达式有些不同。虽然箭头函数提供了简明的语法和一些优势,但要知道何时不能使用它直接替换函数表达式。