EDITED FOR CLARIFICATION
在我說任何事之前,請參閱How Classical Object-Oriented Programming Translates to Javascript。這是非常重要的理解。現在,這就是說,我會繼續:)
JavaScript有一個不幸的特點,你必須非常瞭解運行時環境,以瞭解爲什麼某些語法選擇超過另一個表達相同事情(理論上)。 JavaScript運行環境的一個主要注意事項是,無意中將事情引入全局空間是非常容易的。這裏有兩個快速的例子(這些例子假設你沒有任何其他代碼編寫):
/*
* Example 1
* This example uses 'object literal notation'.
* A link to an article about this is below the example.
* This example shows how easy it is to get into the global space just by
* not declaring variables properly.
*/
var myObj = {
myMethod: function() {
test = 'test'; // oops! now the variable test is in the global
// function space :(
// to avoid this, use var test = 'test'; to keep
// test in the scope of myMethod
}
};
閱讀object literal notation。
/*
* Example 2
* This example shows how the infamous 'this' can be misused to accidentally
* get into the global space.
*/
var myConstructor = function() {
this.test = 'test';
};
var myObj1 = new myConstructor(); // 'this' will by 'myObj1'
var myObj2 = myConstructor(); // 'this' will by the global object :(
要了解爲什麼實例2成立,請參閱this。
避免所有這些問題的方法之一就是遵循控制訪問全局範圍的好模式。正如其中一些答案指出的那樣,您可以將StackExchange
對象視爲用於命名空間的目的,但實際上,它最常用於避免上述示例中列出的問題,還可以防止名稱提升等情況。此外,如果您在使用閉包範圍時非常聰明(利用javascript中的所有範圍都綁定到函數以及在函數中定義函數的事實),則可以使此「命名空間」對象更像傳統的其他經典OOP語言對象javascript是一流的數據對象)。此外,由於全球空間非常危險,最好是「成爲一名優秀的DOM公民」,並且只在全球空間創建一個封裝所有邏輯和數據的對象。
喬爾和傑夫可能實際上設置閉合範圍來做信息隱藏JavaScript的方式。以下僅僅是一個例子:
StackExchange = (function() { // give StackExchange it's own scope to prevent
// name hoisting and also to allow for private
// data
var version = '1.0.0'; // version only seen inside function scope
return { // return an object that will become 'StackExchange' and whose
// methods have access to this function's scope (closure)
debug: (function() {
// set up logging function that will be determined based on
// 'someCondition' (not defined in this code)
var loggingFn = (someCondition) : console.log ? alert;
return { // return obj with access to this function scope
log: function(strToLog) {
loggingFn.call(this, strToLog);
}
};
})(), // immediately execute to make object with 'debug' scope access
getVersion: function() {
return version; // this function has access to StackExchange
// scope; therefore, version will be available
}
};
})(); // immediately execute to make object with 'StackExchange' scope access
欲瞭解更多信息,請參閱name hoisting和scoping。此外,請閱讀Prototypical Inheritance in Javascript以瞭解用於避免全局範圍問題的模式。
感謝例如,我很困惑,我的PHP經驗我熟悉「命名空間 - >類 - >功能或財產」我可以將這一點與此有關,但我有很多東西要學。像語法這樣的東西,我已經看到了JavaScript函數的定義和調用了幾種不同的方式,就好像沒有標準語法(我確定有,只是我的基本JS知識讓我看到) – JasonDavis
我很好奇,可以深入多層次?而'StackExchange = {}'爲什麼'debug:{}'有'':「'而另一個沒有? – JasonDavis
所以,首先,你是對的,有很多方法可以在javascript中表達事物。主要原因在於,在JS中,每當你寫東西的時候,你都必須比大多數其他語言更加註意運行時環境。 – Ryan