根据John Resig的“学习高级JavaScript”(http://ejohn.org/apps/learn/#83),将对象的方法绑定到事件处理程序而不将原始对象作为上下文传递是不正确的,但我发现该示例存在缺陷。它声称被点击的属性被意外设置。这是一个反例。
var Button = {
click: function(){
this.clicked = true;
console.log( elem.clicked );
}
};
var elem = document.createElement("li");
elem.innerHTML = "Click me!";
elem.onclick = Button.click;
document.children[0].appendChild(elem);
console.log( !elem.clicked );
必须有另一个不这样做的理由。它是什么?
答案 0 :(得分:7)
在任何对象方法中,this
始终引用调用方法的对象。 this
提供调用上下文的所有JavaScript都是如此,而不是方法所有者 (*)。
var sample = {
foo: function () {
this.clicked = true;
}
}
sample.foo(); // 'this' refers to 'sample'
alert(sample.clicked) // true
在事件处理程序this
中引用触发事件的元素。这意味着当您将对象方法传递给click
事件...
var div = document.getElementById("test");
div.onclick = sample.foo;
然后{<1}}将在 DOM元素上调用,即使它已在别处定义。
foo()
这将导致意想不到的结果。
(*)这是因为从技术上讲,JavaScript中没有方法所有者。方法是恰好由对象属性引用的独立函数。在不同的对象中存储对同一函数的引用(/* ... click the div ... */
alert(sample.clicked); // false
alert(div.clicked); // true
就是这样)很容易实现。
因此,div.onclick = sample.foo
是句法糖。
obj.method()
答案 1 :(得分:3)
您也可以使用Function.prototype.bind
来解决此问题
elem.onclick = Button.click.bind(Button);
注意 .bind
需要ECMAScript >= 5
答案 2 :(得分:2)
Resig先生所说的是,在JavaScript中,this
的获取方式与this
在其他语言中的工作方式明显不同。在这个例子中,我认为他的观点是在“Button”对象上的“click”函数中对this
的引用不一定是指该对象。相反,它的值仅由调用函数的情况决定。
因此,当您将该函数用作事件处理程序时,函数中this
的值将是对所单击元素的引用。
答案 3 :(得分:0)
这是一个简单的例子,没有事件。
var foo = {
method: function() {
this.prop = true;
}
};
var bar = {};
bar.method = foo.method;
bar.method();
console.log( foo.prop ); // => undefined
console.log( bar.prop ); // => true
foo.method();
console.log( foo.prop ); // => true
在您的示例中,您似乎在点击元素之前检查elem.clicked
的状态。单击它,属性将被设置(但Button.clicked
不会被设置!)。正确的方法是:
elem.onclick = function() { Button.click(); };