2011-02-15 63 views
5

我有JavaScript組件,即具有以下結構:這個指針從內部功能

var MyComponent = function(params) 
{ 
    setup(params); 


    this.doSomething() 
    { 
     // doing something 
    }; 

    function setup(params) 
    { 
     // Setup 

     // Interaction logic 
     var _this = this; // "this" points to DOMWindow, not to created object 
     $(".some-element").click(function(){ 
      _this.doSomething(); // it craches here, because of above 
     }); 
    } 
}; 

當某物,由交互邏輯控制,情況發生時,有時我必須轉發組件的執行爲「公衆」的方法。

在這種情況下,我對「this」指針有問題。

示例代碼演示了:

var Item = function() 
{ 
    this.say = function() 
    { 
     alert("hello"); 
    }; 
    this.sayInternal = function() 
    { 
     _sayInternal(); 
    }; 
    function _sayInternal() 
    { 
     this.say(); 
    }; 
}; 

爲了測試它,

  • 創建一個對象:

var o = new Item();

  • 這工作正常:

o.say(); // alerts "hello"

  • 這種崩潰:

o.sayInternal();

我得到一個錯誤:

TypeError: Result of expression 'this.say' [undefined] is not a function.

我認爲,這樣的行爲發生,因爲_sayInternal ( )函數聲明爲(並未分配給對象,如「this.say = function()」)。這樣,它就在所有創建的對象之間共享,並像C++中的靜態函數一樣工作。

這是真的嗎?

回答

3

不,sayInternal不在創建的對象之間共享。但是你是對的,創建的對象不能訪問sayInternal,因爲它沒有分配給它們。這個函數只對構造函數是本地的。

this總是指函數調用中的環境。如果你這樣稱呼它func(),然後this指的是全局對象(在瀏覽器window)。如果您將函數設置爲對象的屬性並用obj.func()調用它,則this將引用obj

如果您分配一個「綁定」功能給一個變量,並調用它:

var method = obj.func; 
method(); 

然後this將再次引用全局對象。在JavaScript中,函數與其他任何值相似,它們與分配給它的對象沒有特殊的關係。


您可以明確地設置背景與callapply

var MyComponent = function(params) 
{ 
    setup.call(this, params); // <- using `call` 

    this.doSomething() 
    { 
     // doing something 
    }; 

    function setup(params) 
    { 
     // Setup 
     // Interaction logic 
     var _this = this; // "this" to new created object 
     $(".some-element").click(function(){ 
      _this.doSomething(); 
     }); 
    } 
}; 

或者你其他例如:

var Item = function() 
{ 
    this.say = function() 
    { 
     alert("hello"); 
    }; 
    this.sayInternal = function() 
    { 
     _sayInternal.call(this); 
    }; 
    function _sayInternal() 
    { 
     this.say(); 
    }; 
}; 

這就是說,這種做法將功能分配到對象不好,因爲每個實例都會有自己的this.sayInternal功能。因此,對於上面的代碼Item,實例的每次創建都涉及創建三個函數,這是浪費內存。

利用的prototype inheritance將是一個更好的辦法:

var Item = function() { 
}; 

Item.prototype = (function() { 
    function _sayInternal() { 
     this.say(); 
    }; 

    return { 
     say: function() { 
      alert("hello"); 
     }, 
     sayInternal: function(){ 
      _sayInternal.call(this); 
     } 
    } 
}()); 

這樣,_sayInternal只創建一次和所有實例繼承(參考)原型,所以saysayInternal也只出現一次。 即時函數的「竅門」使得_sayInternal僅可由saysayInternal訪問。

+0

謝謝!很好的解釋! – AntonAL 2011-02-15 10:23:25