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

在全局对象中使用“this”的Javascript,javascript,object,this,dom-events,Javascript,Object,This,Dom Events,“this”关键字在全局对象中使用时指的是什么 比如说,我们有: var SomeGlobalObject = { rendered: true, show: function() { /* I should use 'SomeGlobalObject.rendered' below, otherwise it won't work when called from event scope.

“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时未定义

你知道为什么会这样吗? 那么,您能否解释一下,是否有另一种更聪明的方法可以做到这一点,而不必每次都将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);
  }
这样做

var SomeGlobalObject =
  {
     ...
  }

AppendEvent(window, 'load', function(){
    SomeGlobalObject.show();
});
Javascript支持动态范围。因此,SomeGlobalObject将可用于声明为inline always的函数。

执行此操作

var SomeGlobalObject =
  {
     ...
  }

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

Javascript支持动态范围。因此,SomeGlobalObject将可用于声明为inline always的函数。

当您引用一个作为对象方法的函数时,您将其从该对象中分离,而这将不再是对该对象的引用

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

AppendEvent(window, 'load', function () { SomeGlobalObject.show() } );
ECMAScript第5版实现中的函数也有可用的方法,允许您执行以下操作:

AppendEvent(window, 'load', SomeGlobalObject.show.bind(SomeGlobalObject, arg1, arg2));
JS框架原型也适用于当前的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))); 
    }; 
  };
}

当您引用一个作为对象方法的函数时,您正在将其与该对象分离,而这将不再是对该对象的引用

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

AppendEvent(window, 'load', function () { SomeGlobalObject.show() } );
ECMAScript第5版实现中的函数也有可用的方法,允许您执行以下操作:

AppendEvent(window, 'load', SomeGlobalObject.show.bind(SomeGlobalObject, arg1, arg2));
JS框架原型也适用于当前的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))); 
    }; 
  };
}
this关键字始终引用调用对象。在第一个示例中,SomeGlobalObject是调用者

我相信您需要执行类似AppendEventwindow、'load',function{SomeGlobalObject.show}

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


我相信您需要执行类似AppendEventwindow、“load”之类的操作,函数{SomeGlobalObject.show}

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

“this”总是指函数的调用者

因此,就拿这个令人不快的案例来说:

AppendEvent(window, 'load', Msg.show);
事件处理由窗口调用。所以“这”变成了一个窗口和一个窗口

window.rendered
没有定义

bind将很快成为您最好的朋友:-

旁白

window.setTimeout("Msg.show()", 1000);
如果您直接提供函数对象,将运行得更快一些

window.setTimeout(Msg.show, 1000);

这是因为第一种语法要求在调用字符串之前对字符串求值(基本上是编译)

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

“this”总是指函数的调用者

因此,就拿这个令人不快的案例来说:

AppendEvent(window, 'load', Msg.show);
事件处理由窗口调用。所以“这”变成了一个窗口和一个窗口

window.rendered
没有定义

bind将很快成为您最好的朋友:-

旁白

window.setTimeout("Msg.show()", 1000);
如果您直接提供函数对象,将运行得更快一些

window.setTimeout(Msg.show, 1000);

这是因为第一种语法要求在调用字符串之前对字符串进行求值(基本上是编译)

啊,JavaScript,缺少默认方法绑定已经成为第一百万个牺牲品……啊,JavaScript,缺少默认方法绑定已经成为第一百万个牺牲品……或者如果缺少它,自己添加它@博宾斯:谢谢,我一直在寻找:-我真的需要把我的默认搜索提供商切换回谷歌…或者自己添加它,如果它丢失了@博宾斯:谢谢,我一直在寻找:-我真的需要把我的默认搜索提供商切换回谷歌。