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 未定义,因为(出于我不知道的原因)如果 getFoo
在 addEventListener
函数。
现在,如果我在 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.
如果匿名函数中有this
,this
指向window,而不是指向你定义它的地方。比你使用 function
, this
绑定到你定义这个函数的对象。
您可以使用 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
.
的属性
编辑: 这个版本已经过测试并且可以工作。虽然不确定它是否足够简单了......这里的关键是将完全相同的参数传递给 addEventListener
和 removeEventListener
。为此,我为 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();
});
我有以下代码:
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 未定义,因为(出于我不知道的原因)如果 getFoo
在 addEventListener
函数。
现在,如果我在 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
, ornew.target
. These function expressions are best suited for non-method functions, and they cannot be used as constructors.
如果匿名函数中有this
,this
指向window,而不是指向你定义它的地方。比你使用 function
, this
绑定到你定义这个函数的对象。
您可以使用 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
.
编辑: 这个版本已经过测试并且可以工作。虽然不确定它是否足够简单了......这里的关键是将完全相同的参数传递给 addEventListener
和 removeEventListener
。为此,我为 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();
});