如果只需要知道一種編程語言就可以構建一個全棧的應用程式,是不是特別了不起?Ryan Dahl為了把這個想法成為現實,創造了node.js。Node.js是建立在Chrome強勁的V8 JavaScript引擎上的伺服器端框架。雖然最初是用C++編寫的,但是應用程式通過JavaScript運行。 這樣 ...
如果只需要知道一種編程語言就可以構建一個全棧的應用程式,是不是特別了不起?Ryan Dahl為了把這個想法成為現實,創造了node.js。Node.js是建立在Chrome強勁的V8 JavaScript引擎上的伺服器端框架。雖然最初是用C++編寫的,但是應用程式通過JavaScript運行。
這樣一來,問題就解決了。一種語言就可以統治一切。而且,在整個應用程式中你只需要使用這一種語言。所以,我們需要深刻瞭解node.js。這就是本文的主題。
下麵這四個基本概念是你想要掌握node.js所必需的。我會儘可能長話短說向大家介紹它們。
1.非阻塞或非同步I/O
由於Node.js是一種伺服器端框架,所以它的一個主要工作就是處理瀏覽器請求。在傳統的I/O系統中,當前請求只有當先前請求的響應(HTML頁面)已到達才會發出。這就是為什麼它被稱為阻塞I/O。伺服器阻塞其他請求是為了處理當前的請求,而這會導致瀏覽器的等待。
Node.js不遵循I/O的這個原則。如果一個請求需要花費較長時間,那麼Node.js會發送請求到事件迴圈(event loop)中,並繼續在調用棧(call stack)中處理下一個請求。一旦未決請求完成處理,它就會告訴Node.js,並將響應渲染在瀏覽器上。
用一個虛擬的例子來理解這一點:
阻塞I / O
在這個餐廳例子中,服務員給出菜單,等待訂單完成,然後再回到餐桌根據菜單上菜。在當前客戶點菜時,服務員就在旁邊等待,不接受其他客戶的菜單。
非阻塞I / O
在這個例子中,服務員獲得菜單,並告知廚師,然後返回取另一份菜單。在完成第一個菜單進程中,他既按照順序給當前顧客上菜,也接受來自其他客戶的點單。服務員不會因為阻塞來自於其他客戶的點菜而浪費時間。
2.原型
原型是JavaScript的一個複雜概念。不過因為在Node.js中你要多次用到原型,所以每個JavaScript開發人員都必須瞭解這個概念。
在實現經典繼承的語言中,例如Java,或C ++,對於以代碼重用為目的的語言,你首先必須寫一個類,然後從該類創建對象或擴展該類。但是,在JavaScript中不存在類的概念。首先在JavaScript中創建一個對象,然後從這個對象中增加自己的對象,或創建新的對象。這就是所謂的原型傳承和通過原型的實現。
每個JavaScript對象被鏈接到一個來自於它可以繼承屬性的原型對象。原型類似其他OO語言中的類,但不同的是,它們本身也是對象。每一個對象都鏈接到Object.prototype,而Object.prototype自帶JavaScript預定義。
如果你通過obj.propName或 obj['propName'] 查找屬性,而對象並不具有可通過 obj.hasOwnProperty(‘propName’)被檢查的屬性,那麼JavaScript的運行時會在其原型對象中查找屬性。如果原型對象也沒有這樣的屬性,那麼依次檢查它的原型,直到找到匹配,或者到達Object.prototype。如果該屬性不存在原型鏈,那麼它會導致一個未定義的值。
通過下麵的示例代碼來理解這個概念:
當你創建一個新對象的時候,你必須選擇一個應該是它的原型的對象。這裡,我們添加了一個方法到Object function。該方法創建了一個使用另一個對象作為其原型的新對象,而原型作為參數傳遞給它。
當我們改變新對象的時候,它的原型不受影響。但是,當我們進行改變原型對象的時候,這些變化在所有基於該原型的對象上可見。
原型是一個複雜的概念。我將在另一篇文章中詳細說明。
3.模塊
如果你曾經接觸過Java中的包,那麼Node.js中的模塊也沒有什麼不同。如果沒有,那麼也不用擔心。模塊是包含特定目的代碼的簡單的JavaScript文件。模塊模式用來使你的代碼易於導航和使用。要使用模塊屬性,你需要在JavaScript文件中需求它,很像在Java類中導入包。
node.js中有兩種類型的模塊。
核心模塊——這些模塊是用Node.js庫預編譯過的。核心模塊的目的是提供開發者經常發生和重覆的代碼段,這些代碼段如果不可用的話,會導致開發者陷入不得不一次又一次地寫相同代碼的處境。一些常見的核心模塊是HTTP,URL,EVENTS,FILE SYSTEM,等等。
用戶定義模塊——用戶定義模塊是開發人員在應用程式內創建用於特定目的的模塊。當核心模塊不能滿足期望功能的時候就需要用戶定義模塊。
模塊通過require函數提取。如果它是一個核心模塊,那麼參數僅僅是模塊的名稱。如果它是一個用戶自定義模塊,那麼參數就是該模塊在文件系統中的路徑。例如:
4.回調函數
在JavaScript中,函數被認為是第一類對象。這意味著你可以對這些函數做所有可對常規對象做的操作。你可以賦值函數給變數,作為參數傳遞函數給方法,作為對象屬性聲明函數,甚至從函數返回函數。
回調函數是JavaScript中的匿名函數,它可以作為參數傳遞給其他函數,要麼被執行或返回自函數稍後執行。這是回調函數——這個使用最廣的函數編程範式的基礎。
當我們將回調函數作為參數傳遞給另一個函數的時候,我們只能傳遞函數定義……換言之就是,我們不知道這個回調函數什麼時候會執行。這完全取決於調用函數的機制。它會在以後的某個時間點“回調”,因此而得名。這也是非阻塞或Node.js非同步行為的唯一基礎,如下例所示。
這是回調函數最簡單的例子之一。我們將一個匿名函數作為一個參數傳遞,這個參數只需在控制臺上記錄一些輸出到setTimeout函數。它是唯一的函數定義,但是不知道何時執行。這需要經過2秒後,通過第二個參數,調用setTimeout函數來決定。
首先,第二個日誌語句記錄輸出到控制台,然後,2秒鐘後,回調函數中的日誌語句記錄輸出。
上面這些就是Node.js新手必須知道的4個最重要的 JavaScript概念。你的看法呢?希望大家能夠暢所欲言!