代码之家  ›  专栏  ›  技术社区  ›  Marco Demaio

在全局对象中使用“this”的javascript

  •  1
  • Marco Demaio  · 技术社区  · 14 年前

    “this”关键字在gloabl对象中使用时指的是什么?

    比如说我们有:

      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);
      }
    
    4 回复  |  直到 14 年前
        1
  •  4
  •   Andy E    14 年前

    当你引用的函数是一个对象的方法时,你将它从该对象中分离出来 this 将不再是对象的引用。

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

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

    还有 bind 方法可用于ECMAscript第5版实现中的函数,它允许您执行以下操作:

    AppendEvent(window, 'load', Msg.show.bind(Msg, arg1, arg2));
    

    js框架,原型, 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
  •  1
  •   Zoidberg    14 年前

    这样做

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

    javascript支持动态作用域。因此,始终内联声明的函数可以使用someglobalobject。

        3
  •  0
  •   richardtallent    14 年前

    这个 this 关键字始终引用调用对象。在第一个示例中,someglobalobject是调用方。

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

        4
  •  0
  •   plodder    14 年前

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

    “this”总是指函数的调用程序。

    因此,就拿这个冒犯性的案子来说:

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

    事件处理由窗口调用。所以“这个”变成了窗户

    window.rendered
    

    未定义。

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

    作为旁白

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

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

    window.setTimeout(Msg.show, 1000);
    

    这是因为第一个语法需要字符串的eval()-基本上是编译的-才能调用它