Javascript 中在全局上下文中运行的绑定函数

Binding functions in Javascript that operate in the global context

我一直在想弄清楚如何使这段代码工作,这让我自己有点发疯。我的目标是通过将 alice 对象中的函数 eats 绑定到 larry 对象来生成输出 larry eats pie, larry eats candy, larry eats cake。我希望下面的代码是将 alice.eats 函数绑定到 larry 对象将使用 larry 作为 this.name,然后使用 larryFoods 的数组应用该函数,我希望它会为每个参数产生 larry eats + [food]

//-----------------Does not work--------------//
var alice = {
      name: "alice",
      speak: function(){
      console.log("Hi, I'm " + this.name);
      },
      eats : function(){
        var theArgs = Array.prototype.slice.call(arguments);
        theArgs.forEach(function(arg){
          console.log(this.name + " eats " + arg);
        });
      }
};
var larry = {
    name: "larry"
};
var larrySpeak = alice.speak.bind(larry);
larrySpeak();
var larryFoods = [" pie", " candy", " and cake"];
var larryEats = alice.eats.bind(larry);
larryEats.apply(larryFoods);

我假设 forEach 函数将在全局上下文中运行,这就是我希望 bind 能够解决问题的原因。欢迎任何见解。

this 不在 eats 函数中 forEach 内部的 "person" 范围内。或者视觉上:

theArgs.forEach(function(arg){
    // "this".name is trying to resolve name according to the scope of the forEach
    console.log(this.name + " eats " + arg);
});

您可以在 eats 函数中这样修复:

var scope = this;
theArgs.forEach(function(arg){
    console.log(scope.name + " eats " + arg);
});

最后,您需要在最后一行修正 apply 的使用。 apply 需要一个上下文来绑定。由于您已经将函数绑定到 larry,因此您可以将 null 作为第一个参数传递:

这个:

larryEats.apply(larryFoods);

应该是:

larryEats.apply(null, larryFoods);

修复这些问题后,这里是一个工作示例:

var alice = {
  name: "alice",
  speak: function() {
    console.log("Hi, I'm " + this.name);
  },
  eats: function() {
    var theArgs = Array.prototype.slice.call(arguments);
    var scope = this;
    theArgs.forEach(function(arg) {
      console.log(scope.name + " eats " + arg);
    });
  }
};
var larry = {
  name: "larry"
};
var larrySpeak = alice.speak.bind(larry);
larrySpeak();
var larryFoods = ["pie", "candy", "and cake"];
var larryEats = alice.eats.bind(larry);
larryEats.apply(null, larryFoods);

这对我有用:

var alice = {
      name: "alice",
      speak: function(){
      console.log("Hi, I'm " + this.name);
      },
      eats : function(){
        var theArgs = Array.prototype.slice.call(arguments);
        let that = this;
        theArgs.forEach(function(arg){
          console.log(that.name + " eats " + arg);
        });
      }
};
var larry = {
    name: "larry"
};
var larrySpeak = alice.speak.bind(larry);
larrySpeak();
var larryFoods = [" pie", " candy", " and cake"];
var larryEats = alice.eats;
larryEats.apply(larry, larryFoods);