天天看點

AngularJS —— 使用子產品組織你的代碼 【已翻譯100%】(1/3)

介紹

angularjs 的庫裡面有很多東西,但本文中我隻想專注于小的,針對特定主題的庫,我相信通過它們能對angular有一個較好的介紹. 了解這篇文章并不需要你有任何angular相關的,甚至是javascript的經驗。希望你能從本文中看到一些使用angular的好處,并樂于動手嘗試.

背景

我使用angular有一段時間了,而在學習angular的時候,我也喜歡建構一些樣例,是以當我一開始深入進去的時候,對于子產品或者javascript的設計模式,我也沒有多想,那樣對保持代碼組織和條理性有幫助. 那就是所有的重點:保持代碼的組織和條理性. 是以,現在我回過頭來,建立了這個極其小巧的樣例,以展示使用子產品可以有多簡單. 一路走來,我希望它能夠成為一篇好的對angular的介紹.

(大多數)文章在闡述模式時的問題

大多數時候人們都會嘗試去在讀者知道模式是啥概念之前就開始闡述一個模式,而這基本上誤導了每一個人. 這裡要努力使得本文盡量簡單,讓我們首先來看一看這個問題吧。哪個問題呢?就是有關預設會在全局記憶體空間被建立的所有東西的javascript的問題.

下面就是我所說的意思.

javascript 預設的全局問題

設想你的html中有下面這樣一段腳本.

範圍?

你清楚這個變量的範圍麼?

是的,它是全局的。這個布爾值實際上被添加到了浏覽器的全局視窗對象中.

把它設定到action中

這裡你可以看到它在action中是怎樣的.

1.下載下傳本文的代碼樣例.

2.在你的浏覽器中打開 modulepattern.htm .

3.打開浏覽器開發工具 -- f12(chrome, ie) or ctrl-shift-i (opera) -- (那樣就可以看見控制台了)

4.在浏覽器工具控制台下,輸入: isdoingwork,然後回車

5.你會看到輸出的值為false.

6.現在輸入 : isdoingwork = true,然後回車

7.如此下載下傳的值就為true了. 你已經改變了這個值.

8.你可以看到這個值已經通過輸入doingwindow.isdoingwork = true然後回車,被添加到了全局視窗對象之中.

這可能會造成一些名字沖突,也會導緻一些嚴重的bug. 這也許對你而言有點杞人憂天了,是不? 但是請設想你是決定要去實作某一個新的js庫,它每分每秒都可以被建立出來. 假設你發現了這個叫做 panacea.js 的很棒的庫,它将解決你所有的問題.

是以你向下面這樣在你的頁面中引用了它:

如此簡單,你就已經解決之前你遇到的所有問題. 然而,因為它是一個龐大的庫,而你隻想要解決方法,卻不回去深挖這個龐大(幾千行代碼)源檔案裡的每一行代碼. 而深埋在 panacea.js 裡面某個角落的确實下面這樣的代碼:

這代碼真是酷,你知道嗎?

每個3秒,它都會将這個布爾值設定成相對的值。啊!

自己動手看看

如果你想要自己動手驗證下這個東西,你可以做下面這幾步:

1.下載下傳本文的樣例代碼.

2.在你的浏覽器中打開 modulepattern2.htm .

3.打開浏覽器開發工具 -- f12(chrome, ie) 或者 ctrl-shift-i (opera) -- (這樣你就可以看到控制台了)

4.在浏覽器開發工具的控制台下,輸入 : isdoingwork 然後回車

5.将第4步多重複幾次,你将會發現isdoingwork的值會每個大約3秒鐘變化一次.

那這是不是很棒呢?

我的第一個觀點 : 子產品模式是很有用的

我需要為此做出解釋,為了要向你展示為什麼 javascript 的子產品模式是很有用的. 我得想你展示 javascript 的子產品模式,那樣我就可以告訴你它是如何在angularjs中被使用或實作的了.

子產品模式:封裝

如此,實際就是,子產品模式基本上就是封裝了. 封裝聽起來很熟悉,如果你有點面向對象程式設計經曆的話 -- 而我也希望你能有點這個經驗. 封裝是面向對象程式設計的三原則之一。封裝的另外一個說法就是資料隐藏。在經典的面向對象程式設計中——它不同于javascript所依賴的原型化oop -- 資料隐藏是建構一個類模闆的内在組成部分.

例如在 c#中, animal 類的封裝 -- 隐藏資料 -- 特定的值被關聯到animal對象. 那樣,如果某人決定變更那些值,他或他必須明确的通過初始化一個animal對象并設定這個對象的值來達到目的. 在javascript中,我們則可以随意的在全局視窗對象中設定值.

在javascript中,子產品已經被建立用來模拟這種封裝行為了,如此我們就不會去将我們的變量組織到一個全局的命名空間中,并造成了隐藏很深的難以被發現和修複的問題.

現在你知道為什麼了,讓我們來看看如何會是這樣的.

函數被立即調用的表達式(iife)

看上去就好像每次我們向前推進一步,我們都要走點旁門左道. 因為要獲得能讓我們建立子產品模式的javascript文法,我們就得去了解一種叫做函數被立即調用的表達式文法,也叫做iife ( iife 發音是 "iffy").

最基礎的 iife 看起來像這樣:

如果你從來沒有看到過像這樣的東西,那你就有點說不過去了.

立即被調用

首先,這個名稱的第一部分叫做立即被調用的原因是,一般包含這個特殊函數的源檔案被加載好了,那麼包含在這個函數中的代碼就會運作.

對iife文法更加仔細的觀察

你可以看到這個文法的最中心是一個函數。看一下這個代碼塊,我已經将代碼分段并将一些行标上了号,如此我們就可以探讨它了.

首先,看看上面腳本的第2行。這一行通常看來就是一個匿名(也就是沒有命名)的函數聲明. 而後,第3一直到第4則是這個函數的主題部分。最後,第4行最後以一對括弧結束,這對 括弧會告訴javascript解釋器去調用這個函數。最終, 所有這些都會被包在一個不歸屬任何部分的括弧(第1和第5行)中, 而這對括弧會告訴解釋器要調用這個外部的匿名函數,它包含了我們所定義的函數.

iife 可以帶上參數

這段奇怪的文法會在帶上參數之後,看起來會更加的奇怪. 它看起來會像是下面這樣

現在,你可以看到這個函數可以帶上兩個會被内部的函數引用的thing1, thing2參數. 被傳入值,在示例中是 "in string" 和 382.

現在我們了解了iife文法,讓我們來建立另外一個代碼示例,我們将運作這段代碼來看看封裝是如何運作的.

為了看看是怎麼運作的,你可以做下面這幾步:

1.下載下傳本文的源代碼.

2.在你的浏覽器中打開 modulepattern3.htm.

3.打開浏覽器的開發工具 -- f12(chrome, ie) 或者 ctrl-shift-i (opera) -- (這樣你就可以看到控制台了)

4.你可以看到很像下面這樣圖檔中所展示出來的東西

AngularJS —— 使用子產品組織你的代碼 【已翻譯100%】(1/3)

當方法被調用時 -- 這會在代碼被javascript解釋器加載支護立即發生 -- 而後函數會建立 isdoingwork 變量,并調用console.log()來在控制台輸出這個變量的值.

現在,讓我們使用開發工具中的控制台來試試我們之前所嘗試過的步驟:

1.輸入: isdoingwork然後回車

當你這樣做了之後,你将會看到 浏覽器不再相信isdoingwork這個值被定義過。即使是你嘗試從全局視窗對象中擷取這個值, 浏覽器也不認為 isdoingwork 這個值在此對象中被定義了. 你所看到的錯誤消息看起來會像接下來這張圖檔中所展示的這樣.

AngularJS —— 使用子產品組織你的代碼 【已翻譯100%】(1/3)

繼續閱讀