Javascript 中的 Eta 转换

Eta-conversion in Javascript

Eta-conversion 正在考虑函数 (x) => f(x) 与函数 f 相同。在工作中重构代码时,我试图使用这种等价性来简化一些高阶函数调用。然而,事情并没有完全解决,我对实际发生的事情有些迷茫,在 Javascript 还很陌生。这是一个最小的例子,我希望它能正确地说明我的问题。

const station = {
  take: (f) => f(5),
  love: function(car) {
    this.take((x) => car.addFuel(x));
  },
  hate: function(car) {
    this.take(car.addFuel);
  }
};

const mercedes = {
  fuel: 0,
  addFuel: function(amount) {
    this.fuel += amount;
  }
};

station.love(mercedes);
console.log(mercedes.fuel);
// output: 5

station.hate(mercedes);
console.log(mercedes.fuel);
// output: 5; expected output: 10

根据 eta 等价性,我希望 station 对象的 lovehate 函数表现相同。但是,似乎 hate 函数实际上什么也没做。这里发生了什么?

this 存在范围界定问题。在您的原始代码中 hate 回调 this 指的是全局 window 对象。您需要使用 Function.prototype.bind()this.

绑定正确的范围

const station = {
  take: (f) => f(5),
  love: function(car) {
    this.take((x) => car.addFuel(x));
  },
  hate: function(car) {
    this.take(car.addFuel.bind(car));
  }
};

const mercedes = {
  fuel: 0,
  addFuel: function(amount) {
    this.fuel += amount;
  }
};

station.love(mercedes);
console.log(mercedes.fuel);

station.hate(mercedes);
console.log(mercedes.fuel);