2010-03-30 80 views
1

'this'关键字在gloabl对象中使用时指的是什么?javascript在全局对象中使用'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是不确定的。

  1. 你知道为什么会发生这种情况吗?
  2. 你能否解释一下,如果有另一种更智能的方法来做到这一点,而不必每次都将SomeGlobalObject.someProperty重写到SomeGlobalObject代码中?

谢谢!

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); 
    } 
+3

啊,JavaScript,你缺少默认的方法绑定,已经声称它的第一百万个受害者...... – bobince 2010-03-30 13:49:13

回答

4

当您引用作为对象方法的函数时,您将它从该对象中分离出来,并且this将不再是对该对象的引用。

最简单的解决办法是包装在一个匿名函数:

AppendEvent(window, 'load', function() { Msg.show() }); 

还有可用的功能bind方法ECMAScript的第5版实现,它允许你这样做:

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))); 
    }; 
    }; 
} 
+2

......或者如果它缺少,自己添加它。 http://stackoverflow.com/questions/2025789/preserving-a-reference-to-this-in-javascript-prototype-functions/2025839#2025839 – bobince 2010-03-30 13:50:12

+0

@bobince:谢谢,我一直在寻找:-)我真的需要将我的默认搜索提供商切换回Google。 – 2010-03-30 13:52:50

1

做这个

var SomeGlobalObject = 
    { 
    ... 
    } 

AppendEvent(window, 'load', function(){ 
    SomeGlobalObject.show(); 
}); 

的Javascript支持动态作用域。所以SomeGlobalObject将可用于内联始终声明的函数。

0

this关键字总是引用调用对象。在第一个示例中,SomeGlobalObject是调用者。

我相信你会需要做一些像AppendEvent(window, 'load', function() { SomeGlobalObject.show() })

0

一个简单的方法来描述发生了什么:

“这”通常是指函数的调用。

因此,采取违规情况:

AppendEvent(window, 'load', Msg.show); 

事件的处理由窗口调用。所以'这'成为窗口和

window.rendered 

是未定义的。

绑定()将很快成为你最好的朋友:-)

顺便

window.setTimeout("Msg.show()", 1000); 

会跑快一点,如果你提供的函数对象直接

window.setTimeout(Msg.show, 1000); 

这是因为第一个语法需要字符串的eval() - 基本上是编译 - 在它可以被调用之前