箭头函数比传统函数表达式更加简洁:
const add = (a, b) => a + b;
const nums = [1, 2, 3].map(x => x * 2);
虽然语法上简洁,但是在用法上也有一些限制,看看MDN上的说明:
- 箭头函数没有独立的 this、arguments 和 super 绑定,并且不可被用作方法。
- 箭头函数不能用作构造函数。使用 new 调用它们会引发 TypeError。它们也无法访问 new.target 关键字。
- 箭头函数不能在其主体中使用 yield,也不能作为生成器函数创建。
展开讲讲:
- 没有独立的this
// 箭头函数
const obj = {
name: "Alice",
sayName: () => {
console.log(this.name); // this 指向全局对象(如 window)
}
};
obj.sayName(); // undefined(假设全局没有 name)
// 普通函数
const obj = {
name: "Alice",
sayName: function() {
console.log(this.name); // this 指向 obj
}
};
obj.sayName(); // "Alice"
const fn = obj.sayName;
fn(); // undefined(严格模式下 this 是 undefined)
- 没有arguments对象
// 普通函数 带 arguments 对象,包含所有参数:
function sum() {
return Array.from(arguments).reduce((a, b) => a + b);
}
sum(1, 2, 3); // 6
// 箭头函数 没有 arguments 对象,需用剩余参数(...args)代替:
const sum = (...args) => args.reduce((a, b) => a + b);
sum(1, 2, 3); // 6
- 不能用做构造函数
function Person(name) {
this.name = name;
}
const alice = new Person("Alice");
const Person = (name) => { this.name = name; };
new Person("Alice"); // TypeError: Person is not a constructor
了解这个,我们就需要再复习一遍 new 操作符做了什么事情:
- 创建新对象:创建一个空的普通对象
{}。 - 绑定原型:将该对象的原型(
__proto__)指向构造函数的prototype属性。 - 绑定 ****
this:将构造函数内部的this指向这个新对象。 - 执行构造函数:执行构造函数体(初始化属性等)。
- 返回对象:若构造函数未显式返回其他对象,则默认返回这个新对象。
所以箭头函数的核心原因就是:第一没有 prototype属性,第二没有自身的this。两点都和new的工作原理相违背。 并且引擎内部标记箭头函数为 [[IsConstructor]]: false,阻止通过 new 调用。
- 箭头函数的主体中不能使用 yield 关键字
因为yield 表达式只能在生成器函数(function*)的上下文中直接使用:
// 合法:生成器函数
function* regularGenerator() {
yield 1;
}
// 非法:箭头函数中使用 yield
const arrowGenerator = () => {
yield 1; // SyntaxError: Unexpected token 'yield'
};
- 一个小细节,箭头函数的参数和箭头之间不能换行。
const func = (a, b, c)
=> 1;
// SyntaxError: Unexpected token '=>'
- 又一个小细节,更简洁的语法
const func2 = (x, y) => {
return x + y;
};
// 块体语法,需要明确返回值
const func = (x) => x * x;
// 表达式体语法,隐含返回值