我偶然发现了一个问题。我有一个对象方法foo
定义为:
var obj = {
foo: function() {
$('.personName').mouseover(function() {
this.highlight($(this).attr('faceIndex'));
});
}
}
所以应该发生的是,只要鼠标光标位于personName
类型的HTML对象上,就应该使用HTML对象中的obj.highlight
值调用faceIndex
方法作为论点。但是我显然在这两个之间发生了冲突:jQuery和JavaScript之一(从obj
内部引用obj
)。
我可以(应该)做什么?我是否违反了一些优秀的编程习惯?
答案 0 :(得分:2)
解决此问题的典型模式是使用局部变量来存储第一个this
:
var obj = {
foo: function() {
var _this = this;
$('.personName').mouseover(function() {
_this.highlight($(this).attr('faceIndex'));
});
}
}
使用TypeScript或ES6编译器等语言可以更轻松地使用此模式,而无需每次手动编写_this
。
答案 1 :(得分:1)
简短回答:做
$('.personName').mouseover(function(event) {
obj.highlight($(event.target).attr('faceIndex'));
});
更长的解释:
Javascript确实没有 的概念this
。至少不会像你习惯的那样思考它。哦,关键词没问题,而且很多时候你会有所期待,但它并不像你想象的那样工作。
事实是,在javascipt中,this
与任何其他参数没有什么不同。让我告诉你。
大多数人都知道,在javascript中,您可以调用此doSomething(param1, param2)
之类的函数,或者像doSomething.call(null, param1, param2)
这样调用函数。如果需要,可以使用.call
在那里看到null
?你传递的任何内容都是this
设置的内容。
doSomething.call(null, param1, param2);
doSomething.call(obj, param1, param2);
doSomething.call(window, param1, param2);
doSomething.call("foobar", param1, param2);
如果您不使用.call
,运行时只需猜测您想要的值。
因此,考虑到this
与任何其他参数之间的唯一区别是您不能给this
一个名字!你的问题是你有两个函数作用域,而内部函数作用域有一个名为this
的变量,它隐藏了外部的this
。
解决方案:不要使用this
。实际上大多数库(包含jquery),不要强迫您使用this
并将值作为常规参数传递
$('.personName').mouseover(function(event) {
obj.highlight($(event.target).attr('faceIndex'));
});
模糊解决了!
尽可能避免在JavaScript中使用this
。几乎没有必要。
答案 2 :(得分:1)
this
在回调中是很难理解的,因为它几乎可以引用任何实例。这是因为回调是从不同的上下文调用的。
长篇故事:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
我更喜欢处理它的一种方法是使用bind
,也称为proxy
(在JQuery中)。 jQuery在这里实现了一个:jQuery.proxy。
它的好处是让您在回调函数中选择谁是this
。
例如:
var obj = {
foo: function() {
$('.personName').mouseover($.proxy(function(event) {
// this refers here to obj instance
console.log(this);
// event is a jQuery decorated that holds the reference of your element
console.log(event);
}, this));
}
};
它的真正好处在于它可以让你构建那些没有“丑陋”的组件。嵌套回调匿名函数:
var obj = {
foo: function() {
$('.personName').mouseover($.proxy(this.mouseOverCallback, this));
},
mouseOverCallback : function(event) {
// this refers here to obj instance
console.log(this);
// event is a jQuery decorated that holds the reference of your element
console.log(event);
}
};