【问题标题】:Javascript using 'this' in global object在全局对象中使用“this”的 Javascript
【发布时间】:2010-03-30 13:35:50
【问题描述】:

'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("SomeGlobalObject.show()", 1000);

一切正常。

但如果我们这样做:

AppendEvent(window, 'load', SomeGlobalObject.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);
  }

【问题讨论】:

  • 啊,JavaScript,您缺少默认方法绑定已导致其第 100 万个受害者...

标签: javascript object this dom-events


【解决方案1】:

当您引用作为对象方法的函数时,您将其与该对象分离,this 将不再是对该对象的引用。

最简单的解决方案是将其包装在匿名函数中:

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

还有可用于 ECMAScript 第 5 版实现中的函数的 bind 方法,它允许您这样做:

AppendEvent(window, 'load', SomeGlobalObject.show.bind(SomeGlobalObject, 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】:

这样做

var SomeGlobalObject =
  {
     ...
  }

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

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

【讨论】:

    【解决方案3】:

    this 关键字始终指向调用对象。在第一个示例中,SomeGlobalObject 是调用者。

    我相信你需要做类似AppendEvent(window, 'load', function() { SomeGlobalObject.show() })

    【讨论】:

      【解决方案4】:

      描述发生的事情的简单方法:

      'this' 总是指函数的调用者。

      那么就以违规案例为例:

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

      事件处理由窗口调用。所以'this'变成了窗口和

      window.rendered
      

      未定义。

      bind() 很快就会成为你最好的朋友 :-)

      顺便说一句

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

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

      window.setTimeout(Msg.show, 1000);
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-03
        • 1970-01-01
        • 2011-08-06
        • 2014-10-14
        • 1970-01-01
        • 2017-05-06
        • 2013-12-30
        • 1970-01-01
        相关资源
        最近更新 更多