在gloabl对象中使用'this'关键字时会引用什么?
比方说我们有:
var SomeGlobalObject =
{
rendered: true,
show: function()
{
/*
I should use 'SomeGlobalObject.rendered' below, otherwise it
won't work when called from event scope.
But it works when called from timer scope!!
How can this be?
*/
if(this.rendered)
alert("hello");
}
}
现在,如果我们在HTML页面中调用内联脚本:
SomeGlobalObject.show();
window.setTimeout("Msg.show()", 1000);
一切正常。
但是,如果我们做类似
的事情AppendEvent(window, 'load', Msg.show);
我们收到错误,因为从事件范围调用时,this.rendered是未定义的。
谢谢!
AppendEvent只是一个简单的跨浏览器函数来附加一个事件,代码如下,但是为了回答上述问题并不重要。
function AppendEvent(html_element, event_name, event_function)
{
if(html_element.attachEvent) //IE
return html_element.attachEvent("on" + event_name, event_function);
else
if(html_element.addEventListener) //FF
html_element.addEventListener(event_name, event_function, false);
}
答案 0 :(得分:4)
当您引用作为对象方法的函数时,您将其与该对象分离,this
将不再是对象的引用。
最简单的解决方案是将其包装在匿名函数中:
AppendEvent(window, 'load', function () { Msg.show() } );
ECMAScript第5版实现中的函数还有bind
方法,允许您这样做:
AppendEvent(window, 'load', Msg.show.bind(Msg, arg1, arg2));
JS框架,Prototype,provides this method也适用于当前的JS实现。代码(感谢@bobince):
// From Prototype.js
if (!Function.prototype.bind) { // check if native implementation available
Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments),
object = args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
};
};
}
答案 1 :(得分:1)
这样做
var SomeGlobalObject =
{
...
}
AppendEvent(window, 'load', function(){
SomeGlobalObject.show();
});
Javascript支持动态范围。所以SomeGlobalObject将可用于内联声明的函数。
答案 2 :(得分:0)
this
关键字始终引用调用对象。在第一个示例中,SomeGlobalObject是调用者。
我相信你需要做AppendEvent(window, 'load', function() { SomeGlobalObject.show() })
答案 3 :(得分:0)
描述所发生事情的简单方法:
'this'总是指函数的调用者。
所以请采取违法案例:
AppendEvent(window, 'load', Msg.show);
窗口调用事件处理。所以'这'成了窗口和
window.rendered
未定义。
bind()很快会成为你最好的朋友: - )
作为旁白
window.setTimeout("Msg.show()", 1000);
如果直接提供函数对象,会运行得更快
window.setTimeout(Msg.show, 1000);
这是因为第一种语法需要字符串的eval() - 基本上是编译 - 才能被调用