javascript在全局对象中使用'this'

时间:2010-03-30 13:35:51

标签: javascript javascript-events object this

在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是未定义的。

  1. 你知道为什么会这样吗?
  2. 你能解释一下,如果有另一种更聪明的方法可以做到这一点,而不必每次都将SomeGlobalObject.someProperty重写成SomeGlobalObject代码吗?
  3. 谢谢!

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

4 个答案:

答案 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() - 基本上是编译 - 才能被调用