文章目錄
JavaScript編程思想,這個編程思想挺偉大的詞在我的心裡其實很糾結。JavaScript 命名空間的資料在網上一搜一大把,本人只是做個學習的小結。
網上常見的代碼,都常見得快爛透了,因為方便+簡單嘛:
var GLOBAL = { str: 'linkClass', init: function(){ return str; }};
上面也是本人受前端牛人指點時的經典代碼。經典到前段時間我才從中走出來。
不想固步自封?那就下一步了。不過,在下一步之前先看與之等價的代碼:
var GLOBAL = {};GLOBAL.str='linkClass';GLOBAL.init=function(){ return str;};
呃,因為只要會寫JavaScript,都會上面的了(瞧瞧這哥們寫的)。那麼這下一步其實還是等價的代碼:
var GLOBAL = {};GLOBAL['str']='linkClass';GLOBAL['init']=function(){ return str;};
問題是上面的對象中的屬性和方法沒有達到松耦合,一直都還沒有實現物件導向最最基本的封裝特性。你看str屬性其實不必給暴露出來,因為init方法的作用就是返回str的值。所以:
(function(){var str='linkClass';function init(){ return str;}window['GLOBAL']={};window['GLOBAL']['init']=init;})();
這樣寫的好處解釋下:在命名空間下定義的屬性或方法是全域的,也就是等於暴露出去的介面,而私用變數在 JavaScript 閉包外是無法 get 和 set 的。str 從函數 init 內找起,然後沿著範圍鏈找到了它。也達到了松耦合。
松耦合的概念我是在Yahoo前端從庫往架構走的這麼一個“理念”中看到的。
所以,從這段代碼的來源中學習後就震撼了,上面我的解釋挺民科的,下面摘錄《JavaScript 權威指南(第5版)》中8.8.2節的內容:
It is sometimes useful to define a function simply to create a call object that acts as a temporary namespace in which you can define variables and create properties without corrupting the global namespace. Suppose, for example, you have a file of JavaScript code that you want to use in a number of different JavaScript programs (or, for client-side JavaScript, on a number of different web pages). Assume that this code, like most code, defines variables to store the intermediate results of its computation. The problem is that since this code will be used in many different programs, you don't know whether the variables it creates will conflict with variables used by the programs that import it.
The solution, of course, is to put the code into a function and then invoke the function. This way, variables are defined in the call object of the function:
function init() { // Code goes here. // Any variables declared become properties of the call // object instead of cluttering up the global namespace.}init(); // But don't forget to invoke the function!
The code adds only a single property to the global namespace: the property "init", which refers to the function. If defining even a single property is too much, you can define and invoke an anonymous function in a single expression. The code for this JavaScript idiom looks like this:
(function() { // This function has no name. // Code goes here. // Any variables declared become properties of the call // object instead of cluttering up the global namespace.})(); // end the function literal and invoke it now.
Note that the parentheses around the function literal are required by JavaScript syntax.
hax說,IE有全域變數DID(人格分裂症)。所以,請慎用!另外,這不是所謂的“JS分層概念”。
更新於 2010.1.29
另一種方法是用函數作為命名空間,請見 David 原文《Functions as Namespaces, and How to Peek Inside》及譯文《如何訪問作為命名空間的函數內部變數》。