2010-03-30 79 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() - 基本上是編譯 - 在它可以被調用之前