2012-03-07 112 views
4

我想圍繞建設一個自定義的JavaScript庫頭。我閱讀了很多關於模塊模式的內容,還閱讀了克羅克福德關於私人和公衆成員的文章。我知道什麼是一個立即調用的函數表達式,爲什麼我們做的東西一樣Javascript模塊模式,範圍和「這」

var myLib = (function() { 
}()) 

不過,我仍然在關於一般範圍和封閉某些情況下,有點失落。我遇到的具體問題是:

爲什麼下面的示例警告DOMWindow,而不是myLib對象? http://jsfiddle.net/slavo/xNJtW/1/

如果你能解釋這個例子中的所有方法和原因是什麼,這將是很好的解釋。

+2

僅供參考:此變量與變量範圍無關。它只與該函數的調用上下文有關。它的值取決於* how *函數的調用方式。 – 2012-03-07 16:20:06

+3

順便說一句,你可以''使用嚴格的''爲了使這種情況下的「this」是未定義的而不是窗口。它可以幫助很多有這種錯誤更明確地顯示。 – hugomg 2012-03-07 18:27:44

回答

3

內聲明(任何地方),並調用任何功能如下this將是window對象

function anyFunc(){ 
    alert(this); // window object 
} 

anyFunc(); 


var anyFunc2 = function(){ 
    alert(this); // window object 
} 

anyFunc2(); 

如果你想創建私人活動和訪問「myObject的」的情況下,你可以按照下列方法的

一個

module = (function() { 

    var privateFunc = function() { 
     alert(this); 
    } 

    var myObject = { 
     publicMethod: function() { 
      privateFunc.apply(this); // or privateFunc.call(this); 
     } 
    }; 

    return myObject; 
}()); 


module.publicMethod(); 

兩個

module = (function() { 

    var _this; // proxy variable for instance 

    var privateFunc = function() { 
     alert(_this); 
    } 

    var myObject = { 
     publicMethod: function() { 
      privateFunc(); 
     } 
    }; 
    _this = myObject; 
    return myObject; 
}()); 


module.publicMethod(); 

這些都是解決您的問題的方法。我會建議使用基於原型的對象。

編輯:

您可以使用第一種方法。

其實這裏myObject是在相同的範圍內privateFunc,你可以直接使用它的功能

var privateFunc = function() { 
    alert(myObject); 
} 

真正的情況是,你可以使用代理this如下所示內。您也可以使用call

Module = function() { 

    var _this; // proxy variable for instance 

    var privateFunc = function() { 
     alert(this + "," + _this); 
    } 

    this.publicMethod = function() { 
     privateFunc(); // alerts [object Window],[object Object] 
     privateFunc.call(this); // alerts [object Object],[object Object] 
    } 

    _this = this; 
    return this; 
}; 

var module = new Module(); 
module.publicMethod(); 
+0

爲什麼要創建'_this'?在一個對象內部,'this'應該像'obj.foo()' – Sarfraz 2012-03-07 16:27:45

+0

這樣調用時引用該對象。回答是在你的問題 - 「內部對象」中。在這裏你可以看到'privateFunc'不在'myObject'中,意味着沒有被定義爲'myObject'的函數。所以我們必須使用代理變量。 – Diode 2012-03-07 16:33:50

+0

在'myObject'的所有函數中,''this'在使用點運算符調用時是'myObject' - 例如:'myObject.publicMethod();' – Diode 2012-03-07 16:37:15

-1

在您的鏈接的小提琴中,「this」關鍵字永遠不會被「新」關鍵字或其他上下文更改所改變,因此它仍然引用全局窗口對象。

編輯:澄清

+2

*'「this」永遠不會被「新」關鍵字所改變...所以它指的是全局窗口對象。'*完全錯誤。 – 2012-03-07 16:14:11

+0

@amnotiam你能解釋一下/爲什麼它是錯的?我想學習一些東西,而不是僅僅被侮辱:P – jbabey 2012-03-07 18:01:09

+0

*「這個」永遠不會被一個「新」關鍵字所改變......「*刪除」永不「這個詞並將其替換爲」永遠「。 *「...或其他範圍更改...」*'new'不會導致範圍更改。它導致調用上下文('this')的改變。 *「...所以它指的是全局窗口對象。」*什麼時候this指的是全局窗口對象?當使用'new'時?在這種情況下,它永遠不會涉及全球。除此之外,它將取決於函數的調用方式。對不起,如果你感到侮辱。 – 2012-03-07 18:26:01

0

你需要明確指出myPrivateMethod是MYLIB中的一員:

function MyLib() 
{ 
    this._myPrivateField = "private"; 
    this._myPrivateMEthod = function() 
    { 
     alert(this); // Alerts MyLib function; 
    } 
} 

var libObject = new MyLib(); 

只要記住,不使用外殼技術,沒有在JavaScript是曾經真正私有!

一種更好的方式上面做的是像這樣:

function MyLib(instanceName) 
{ 
    this.name = instanceName; 
} 

MyLib.prototype.myPrivateFunction() 
{ 
    alert(this); 
} 

後調用你的方法:

var libObject = new MyLib(); 
libObject.myPrivateMethod(); // Alerts info about libObject. 
+0

在這種情況下,我怎麼能從公共方法(我的示例中返回的對象的成員)調用私有方法? – Slavo 2012-03-07 16:15:58

+1

爲什麼使用後者更好? – 2012-03-07 16:16:23

+0

對不起。編輯上面包括! – 2012-03-07 16:16:53

0

要記住模塊模式的事情是,它運行一次,完成。仍然可以調用的方法是閉包。在創建模塊時,「this」引用窗口並被其值替換。