Javascript 'this' returns 对象内部未定义

Javascript 'this' returns undefined inside object

我有以下代码:

let myObj = {
  foo: "bar",
  getFoo: function() {
    console.log(this.foo);
  },
  method: function() {
    if (true) {
      window.addEventListener('scroll', this.getFoo);
    } else {
      window.removeEventListener('scroll', this.getFoo);
    }
  }
}

window.addEventListener('click', () => {
  myObj.method();
});

它 returns 未定义,因为(出于我不知道的原因)如果 getFooaddEventListener 函数。 现在,如果我在 myObj.method -

中使用箭头函数
window.addEventListener('scroll', () => {
  this.getFoo();
});

这会起作用,但后来我调用了一个匿名函数,以后无法执行 removeEventListener。 我怎样才能使它与非匿名函数一起使用?

来自MDN

An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors.

如果匿名函数中有thisthis指向window,而不是指向你定义它的地方。比你使用 functionthis 绑定到你定义这个函数的对象。

您可以使用 call and bind 在特定对象的上下文中调用方法或函数,以便 this 引用 myObj 的上下文:

let myObj = {
  foo: "bar",
  getFoo: function() {
    console.log(this.foo);
  },
  method: function() {
    if (true) {
      // here you have to use bind to create a function in a certain context
      window.addEventListener('scroll', this.getFoo.bind(this));
    } else {
      // here is the same
      window.removeEventListener('scroll', this.getFoo.bind(this));
    }
  }
}

window.addEventListener('click', () => {
  // create and call method in the context of myObj or any other object that is passed as first parameter of call
  myObj.method.call(myObj);
  // or because this in the function method refers to myObj at the beginning, just call method with obj
  myObj.method();
});

如果您想了解 "this" 关键字的实际工作原理,我建议您快速浏览一下 here...

您的问题的解决方案可能是创建一个名为 selfObj 的变量(或类似的东西),然后使用它来访问 myObj.

的属性

编辑: 这个版本已经过测试并且可以工作。虽然不确定它是否足够简单了......这里的关键是将完全相同的参数传递给 addEventListenerremoveEventListener。为此,我为 myObj 对象创建了 scrollEventListener 数组属性。然后使用 destructuring 将其作为参数传递...

希望这对您有所帮助...

'use strict';

    let myObj = {
        foo: 'bar',
        counter: 0,
        getFoo: function() {
            const selfObj = this;
            console.log(selfObj.foo);
        },
        scrollEventListener: [
            'scroll',
            function () {
                myObj.getFoo();
            },
            true
        ],
        method: function() {
            const selfObj = this;
            selfObj.counter++;
            if (selfObj.counter % 2 === 0) {
                window.addEventListener(...selfObj.scrollEventListener);
            } else {
                window.removeEventListener(...selfObj.scrollEventListener);
            }
        }
    };

    window.addEventListener('click', () => {
        myObj.method();
    });