箭头函数没有自己的 this
值和 arguments
对象。因此,你不应该将它用作事件的回调函数、字面量对象的方法、原型的方法。
如果当你需要在函数使用 arguments
对象时,你也不应该使用箭头函数。在本教程中,您将了解在 ES6 什么时候不该使用箭头函数。
事件处理器
假设您的HTML代码有以下文本输入字段:
<input type="text" name="username" id="username" placeholder="Enter a username">
您希望在用户键入用户名时显示问候消息。下面将在 <div>
元素显示问候消息:
<div id="greeting"></div>
用户输入用户名后,您将捕获输入的当前值并将其更新到 <div>
元素:
const greeting = document.querySelector('#greeting');
const username = document.querySelector('#username');
username.addEventListener('keyup', () => {
greeting.textContent = 'Hello ' + this.value;
});
但是,当您执行代码时,无论您键入什么,您都会收到以下消息:
Hello undefined
这意味着事件回调函数总是返回undefined
。
如前所述,箭头函数没有自己的 this
值。它在封闭词法作用域使用 this
值。在上面的例子中,箭头函数的 this
引用全局对象。
在网络浏览器,全局对象是 window
。 window
对象没有属性 value
。因此,JavaScript 引擎将 value 属性添加到 window
对象并将其值设置为 undefined
。
要解决此问题,您需要改用普通函数。this
值将绑定到触发事件的 <input>
元素。
username.addEventListener('keyup', function () {
input.textContent = 'Hello ' + this.value;
});
对象方法
请阅读以下 counter
对象:
const counter = {
count: 0,
next: () => ++this.count,
current: () => this.count
};
counter
对象有两个方法: current()
和 next()
。current()
方法返回当前计数器值,next()
方法返回下一个计数器值。
下面计数器应该展示下一个值是 1:
console.log(counter.next());
但是,它返回 NaN
。
原因是当你在对象内部使用箭头函数时,它从封闭的词法作用域继承 this
值,在这个例子中是全局作用域。
this.count
在 next()
方法内部相当于 window.count
(Web 浏览器)。
默认情况下 window.count
是 undefined
。因为 window
对象没有 count
属性。next()
方法在 undefined
的变量上再加 1 ,所以结果是 NaN
。
要解决此问题,您可以使用普通函数作为字面量对象的方法,如下所示:
const counter = {
count: 0,
next() {
return ++this.count;
},
current() {
return this.count;
}
};
现在,调用 next()
方法将按预期返回 1:
console.log(counter.next()); // 1
原型方法
请阅读以下使用 prototype
模式的 Counter
对象:
function Counter() {
this.count = 0;
}
Counter.prototype.next = () => {
return this.count;
};
Counter.prototype.current = () => {
return ++this.next;
}
this
值在 next()
和 current()
方法中指向全局对象。由于您希望在这些方法中的 this
值指向 Counter
对象,因此您需要改用普通函数:
function Counter() {
this.count = 0;
}
Counter.prototype.next = function () {
return this.count;
};
Counter.prototype.current = function () {
return ++this.next;
}
使用 arguments 参数对象的函数
箭头函数没有 arguments
对象 。因此,如果你有一个函数使用 arguments
对象,你就不能使用箭头函数。
例如,下面的 concat()
函数将不起作用:
const concat = (separator) => {
let args = Array.prototype.slice.call(arguments, 1);
return args.join(separator);
}
相反,您可以这样使用普通函数:
function concat(separator) {
let args = Array.prototype.slice.call(arguments, 1);
return args.join(separator);
}
结论
- 箭头函数没有自己的
this
值。相反,它使用封闭词法作用域的this
值。箭头函数也没有arguments
对象。 - 避免将箭头函数用于事件回调、字面量对象方法、原型方法和使用
arguments
对象的函数。