面试官又让我说ES6的箭头函数

112 阅读2分钟

箭头函数比传统函数表达式更加简洁:

const add = (a, b) => a + b;

const nums = [1, 2, 3].map(x => x * 2);

虽然语法上简洁,但是在用法上也有一些限制,看看MDN上的说明:

展开讲讲:

  1. 没有独立的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)
  1. 没有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
  1. 不能用做构造函数
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 操作符做了什么事情:

  1. 创建新对象:创建一个空的普通对象 {}
  2. 绑定原型:将该对象的原型(__proto__)指向构造函数的 prototype 属性。
  3. 绑定 ****this:将构造函数内部的 this 指向这个新对象。
  4. 执行构造函数:执行构造函数体(初始化属性等)。
  5. 返回对象:若构造函数未显式返回其他对象,则默认返回这个新对象。

所以箭头函数的核心原因就是:第一没有 prototype属性,第二没有自身的this。两点都和new的工作原理相违背。 并且引擎内部标记箭头函数为 [[IsConstructor]]: false,阻止通过 new 调用。

  1. 箭头函数的主体中不能使用 yield 关键字

因为yield 表达式只能在生成器函数(function*)的上下文中直接使用:

// 合法:生成器函数
function* regularGenerator() {
  yield 1;
}

// 非法:箭头函数中使用 yield
const arrowGenerator = () => {
  yield 1; // SyntaxError: Unexpected token 'yield'
};
  1. 一个小细节,箭头函数的参数和箭头之间不能换行。
const func = (a, b, c)
  => 1;
// SyntaxError: Unexpected token '=>'
  1. 又一个小细节,更简洁的语法
const func2 = (x, y) => {
  return x + y;
};
// 块体语法,需要明确返回值

const func = (x) => x * x;
// 表达式体语法,隐含返回值