Node初學者入門,一本全面的NodeJS教程(上)

2021-03-02 優才網
摘要

本書致力於教會你如何用Node.js來開發應用,在這過程中會傳授你所有所需的「高級」JavaScript知識。本書絕不是一本「Hello World」的教程。優優希望你細細讀之,必有所獲。

教程內容較長,由於微信對文章篇幅有限制,所以將分為三部分進行分享。

狀態

你正在閱讀的已經是本書的最終版。因此,只有當進行錯誤更正以及針對新版本Node.js的改動進行對應的修正時,才會進行更新。

本書中的代碼案例都在Node.js 0.6.11版本中測試過,可以正確工作。

讀者對象

本書最適合與我有相似技術背景的讀者: 至少對一門諸如Ruby、Python、PHP或者Java這樣面向對象的語言有一定的經驗;對JavaScript處於初學階段,並且完全是一個Node.js的新手。

這裡指的適合對其他程式語言有一定經驗的開發者,意思是說,本書不會對諸如數據類型、變量、控制結構等等之類非常基礎的概念作介紹。要讀懂本書,這些基礎的概念我都默認你已經會了。

然而,本書還是會對JavaScript中的函數和對象作詳細介紹,因為它們與其他同類程式語言中的函數和對象有很大的不同。

本書結構

讀完本書之後,你將完成一個完整的web應用,該應用允許用戶瀏覽頁面以及上傳文件。

當然了,應用本身並沒有什麼了不起的,相比為了實現該功能書寫的代碼本身,我們更關注的是如何創建一個框架來對我們應用的不同模塊進行乾淨地剝離。 是不是很玄乎?稍後你就明白了。

本書先從介紹在Node.js環境中進行JavaScript開發和在瀏覽器環境中進行JavaScript開發的差異開始。

緊接著,會帶領大家完成一個最傳統的「Hello World」應用,這也是最基礎的Node.js應用。

最後,會和大家討論如何設計一個「真正」完整的應用,剖析要完成該應用需要實現的不同模塊,並一步一步介紹如何來實現這些模塊。

可以確保的是,在這過程中,大家會學到JavaScript中一些高級的概念、如何使用它們以及為什麼使用這些概念就可以實現而其他程式語言中同類的概念就無法實現。

該應用所有的原始碼都可以通過 本書Github代碼倉庫(https://github.com/ManuelKiessling/NodeBeginnerBook/tree/master/code/application)

目錄

JavaScript與Node.jsJavaScript與你

拋開技術,我們先來聊聊你以及你和JavaScript的關係。本章的主要目的是想讓你看看,對你而言是否有必要繼續閱讀後續章節的內容。

如果你和我一樣,那麼你很早就開始利用HTML進行「開發」,正因如此,你接觸到了這個叫JavaScript有趣的東西,而對於JavaScript,你只會基本的操作——為web頁面添加交互。

而你真正想要的是「乾貨」,你想要知道如何構建複雜的web站點 —— 於是,你學習了一種諸如PHP、Ruby、Java這樣的程式語言,並開始書寫「後端」代碼。

與此同時,你還始終關注著JavaScript,隨著通過一些對jQuery,Prototype之類技術的介紹,你慢慢了解到了很多JavaScript中的進階技能,同時也感受到了JavaScript絕非僅僅是window.open() 那麼簡單。 .

不過,這些畢竟都是前端技術,儘管當想要增強頁面的時候,使用jQuery總讓你覺得很爽,但到最後,你頂多是個JavaScript用戶,而非JavaScript開發者。

然後,出現了Node.js,服務端的JavaScript,這有多酷啊?

於是,你覺得是時候該重新拾起既熟悉又陌生的JavaScript了。但是別急,寫Node.js應用是一件事情;理解為什麼它們要以它們書寫的這種方式來書寫則意味著——你要懂JavaScript。這次是玩真的了。

問題來了: 由於JavaScript真正意義上以兩種,甚至可以說是三種形態存在(從中世紀90年代的作為對DHTML進行增強的小玩具,到像jQuery那樣嚴格 意義上的前端技術,一直到現在的服務端技術),因此,很難找到一個「正確」的方式來學習JavaScript,使得讓你書寫Node.js應用的時候感覺 自己是在真正開發它而不僅僅是使用它。

因為這就是關鍵: 你本身已經是個有經驗的開發者,你不想通過到處尋找各種解決方案(其中可能還有不正確的)來學習新的技術,你要確保自己是通過正確的方式來學習這項技術。

當然了,外面不乏很優秀的學習JavaScript的文章。但是,有的時候光靠那些文章是遠遠不夠的。你需要的是指導。

本書的目標就是給你提供指導。

簡短申明

業界有非常優秀的JavaScript程式設計師。而我並非其中一員。

我就是上一節中描述的那個我。我熟悉如何開發後端web應用,但是對「真正」的JavaScript以及Node.js,我都只是新手。我也只是最近學習了一些JavaScript的高級概念,並沒有實踐經驗。

因此,本書並不是一本「從入門到精通」的書,更像是一本「從初級入門到高級入門」的書。

如果成功的話,那麼本書就是我當初開始學習Node.js最希望擁有的教程。

服務端JavaScript

JavaScript最早是運行在瀏覽器中,然而瀏覽器只是提供了一個上下文,它定義了使用JavaScript可以做什麼,但並沒有「說」太多關於 JavaScript語言本身可以做什麼。事實上,JavaScript是一門「完整」的語言: 它可以使用在不同的上下文中,其能力與其他同類語言相比有過之而無不及。

Node.js事實上就是另外一種上下文,它允許在後端(脫離瀏覽器環境)運行JavaScript代碼。

要實現在後臺運行JavaScript代碼,代碼需要先被解釋然後正確的執行。Node.js的原理正是如此,它使用了Google的V8虛擬機 (Google的Chrome瀏覽器使用的JavaScript執行環境),來解釋和執行JavaScript代碼。

除此之外,伴隨著Node.js的還有許多有用的模塊,它們可以簡化很多重複的勞作,比如向終端輸出字符串。

因此,Node.js事實上既是一個運行時環境,同時又是一個庫。

要使用Node.js,首先需要進行安裝。關於如何安裝Node.js,這裡就不贅述了,可以直接參考官方的安裝指南。安裝完成後,繼續回來閱讀本書下面的內容。

「Hello World」

好了,「廢話」不多說了,馬上開始我們第一個Node.js應用:「Hello World」。

打開你最喜歡的編輯器,創建一個helloworld.js文件。我們要做就是向STDOUT輸出「Hello World」,如下是實現該功能的代碼:

console.log("Hello World");

保存該文件,並通過Node.js來執行:

node helloworld.js

正常的話,就會在終端輸出Hello World 。

好吧,我承認這個應用是有點無趣,那麼下面我們就來點「乾貨」。

一個完整的基於Node.js的web應用用例

我們來把目標設定得簡單點,不過也要夠實際才行:

差不多了,你現在也可以去Google一下,找點東西亂搞一下來完成功能。但是我們現在先不做這個。

更進一步地說,在完成這一目標的過程中,我們不僅僅需要基礎的代碼而不管代碼是否優雅。我們還要對此進行抽象,來尋找一種適合構建更為複雜的Node.js應用的方式。

應用不同模塊分析

我們來分解一下這個應用,為了實現上文的用例,我們需要實現哪些部分呢?

我們需要提供Web頁面,因此需要一個HTTP伺服器

對於不同的請求,根據請求的URL,我們的伺服器需要給予不同的響應,因此我們需要一個路由,用於把請求對應到請求處理程序(request handler)

當請求被伺服器接收並通過路由傳遞之後,需要可以對其進行處理,因此我們需要最終的請求處理程序

路由還應該能處理POST數據,並且把數據封裝成更友好的格式傳遞給請求處理入程序,因此需要請求數據處理功能

我們不僅僅要處理URL對應的請求,還要把內容顯示出來,這意味著我們需要一些視圖邏輯供請求處理程序使用,以便將內容發送給用戶的瀏覽器

最後,用戶需要上傳圖片,所以我們需要上傳處理功能來處理這方面的細節

我們先來想想,使用PHP的話我們會怎麼構建這個結構。一般來說我們會用一個Apache HTTP伺服器並配上mod_php5模塊。
從這個角度看,整個「接收HTTP請求並提供Web頁面」的需求根本不需要PHP來處理。

不過對Node.js來說,概念完全不一樣了。使用Node.js時,我們不僅僅在實現一個應用,同時還實現了整個HTTP伺服器。事實上,我們的Web應用以及對應的Web伺服器基本上是一樣的。

聽起來好像有一大堆活要做,但隨後我們會逐漸意識到,對Node.js來說這並不是什麼麻煩的事。

現在我們就來開始實現之路,先從第一個部分--HTTP伺服器著手。

構建應用的模塊一個基礎的HTTP伺服器

當我準備開始寫我的第一個「真正的」Node.js應用的時候,我不但不知道怎麼寫Node.js代碼,也不知道怎麼組織這些代碼。 
我應該把所有東西都放進一個文件裡嗎?網上有很多教程都會教你把所有的邏輯都放進一個用Node.js寫的基礎HTTP伺服器裡。但是如果我想加入更多的內容,同時還想保持代碼的可讀性呢?

實際上,只要把不同功能的代碼放入不同的模塊中,保持代碼分離還是相當簡單的。

這種方法允許你擁有一個乾淨的主文件(main file),你可以用Node.js執行它;同時你可以擁有乾淨的模塊,它們可以被主文件和其他的模塊調用。

那麼,現在我們來創建一個用於啟動我們的應用的主文件,和一個保存著我們的HTTP伺服器代碼的模塊。

在我的印象裡,把主文件叫做index.js或多或少是個標準格式。把伺服器模塊放進叫server.js的文件裡則很好理解。

讓我們先從伺服器模塊開始。在你的項目的根目錄下創建一個叫server.js的文件,並寫入以下代碼:

var http = require("http");

http.createServer(function(request, response){
  response.writeHead(200,{"Content-Type":"text/plain"});
  response.write("Hello World");
  response.end();
}).listen(8888);

搞定!你剛剛完成了一個可以工作的HTTP伺服器。為了證明這一點,我們來運行並且測試這段代碼。首先,用Node.js執行你的腳本:

node server.js

接下來,打開瀏覽器訪問http://localhost:8888/,你會看到一個寫著「Hello World」的網頁。

這很有趣,不是嗎?讓我們先來談談HTTP伺服器的問題,把如何組織項目的事情先放一邊吧,你覺得如何?我保證之後我們會解決那個問題的。

分析HTTP伺服器

那麼接下來,讓我們分析一下這個HTTP伺服器的構成。

第一行請求(require)Node.js自帶的 http 模塊,並且把它賦值給 http 變量。

接下來我們調用http模塊提供的函數: createServer 。這個函數會返回一個對象,這個對象有一個叫做 listen的方法,這個方法有一個數值參數,指定這個HTTP伺服器監聽的埠號。

咱們暫時先不管 http.createServer 的括號裡的那個函數定義。

我們本來可以用這樣的代碼來啟動伺服器並偵聽8888埠:

var http = require("http");

var server = http.createServer();
server.listen(8888);

這段代碼只會啟動一個偵聽8888埠的伺服器,它不做任何別的事情,甚至連請求都不會應答。

最有趣(而且,如果你之前習慣使用一個更加保守的語言,比如PHP,它還很奇怪)的部分是 createSever()的第一個參數,一個函數定義。

實際上,這個函數定義是 createServer() 的第一個也是唯一一個參數。因為在JavaScript中,函數和其他變量一樣都是可以被傳遞的。

進行函數傳遞

舉例來說,你可以這樣做:

function say(word){
  console.log(word);
}

function execute(someFunction, value){
  someFunction(value);
}

execute(say,"Hello");

請仔細閱讀這段代碼!在這裡,我們把 say 函數作為execute函數的第一個變量進行了傳遞。這裡返回的不是say 的返回值,而是 say 本身!

這樣一來, say 就變成了execute 中的本地變量 someFunction ,execute可以通過調用 someFunction() (帶括號的形式)來使用 say 函數。

當然,因為 say 有一個變量, execute 在調用 someFunction 時可以傳遞這樣一個變量。

我們可以,就像剛才那樣,用它的名字把一個函數作為變量傳遞。但是我們不一定要繞這個「先定義,再傳遞」的圈子,我們可以直接在另一個函數的括號中定義和傳遞這個函數:

function execute(someFunction, value){
  someFunction(value);
}

execute(function(word){ console.log(word)},"Hello");

我們在 execute 接受第一個參數的地方直接定義了我們準備傳遞給 execute 的函數。

用這種方式,我們甚至不用給這個函數起名字,這也是為什麼它被叫做 匿名函數 。

這是我們和我所認為的「進階」JavaScript的第一次親密接觸,不過我們還是得循序漸進。現在,我們先接受這一點:在JavaScript中,一個 函數可以作為另一個函數接收一個參數。我們可以先定義一個函數,然後傳遞,也可以在傳遞參數的地方直接定義函數。

函數傳遞是如何讓HTTP伺服器工作的

帶著這些知識,我們再來看看我們簡約而不簡單的HTTP伺服器:

var http = require("http");

http.createServer(function(request, response){
  response.writeHead(200,{"Content-Type":"text/plain"});
  response.write("Hello World");
  response.end();
}).listen(8888);

現在它看上去應該清晰了很多:我們向 createServer 函數傳遞了一個匿名函數。

用這樣的代碼也可以達到同樣的目的:

var http = require("http");

function onRequest(request, response){
  response.writeHead(200,{"Content-Type":"text/plain"});
  response.write("Hello World");
  response.end();
}

http.createServer(onRequest).listen(8888);

也許現在我們該問這個問題了:我們為什麼要用這種方式呢?

基於事件驅動的回調

這個問題可不好回答(至少對我來說),不過這是Node.js原生的工作方式。它是事件驅動的,這也是它為什麼這麼快的原因。

你也許會想花點時間讀一下Felix Geisendörfer的大作Understanding node.js,它介紹了一些背景知識。

這一切都歸結於「Node.js是事件驅動的」這一事實。好吧,其實我也不是特別確切的了解這句話的意思。不過我會試著解釋,為什麼它對我們用Node.js寫網絡應用(Web based application)是有意義的。

當我們使用 http.createServer 方法的時候,我們當然不只是想要一個偵聽某個埠的伺服器,我們還想要它在伺服器收到一個HTTP請求的時候做點什麼。

問題是,這是異步的:請求任何時候都可能到達,但是我們的伺服器卻跑在一個單進程中。

寫PHP應用的時候,我們一點也不為此擔心:任何時候當有請求進入的時候,網頁伺服器(通常是Apache)就為這一請求新建一個進程,並且開始從頭到尾執行相應的PHP腳本。

那麼在我們的Node.js程序中,當一個新的請求到達8888埠的時候,我們怎麼控制流程呢?

嗯,這就是Node.js/JavaScript的事件驅動設計能夠真正幫上忙的地方了——雖然我們還得學一些新概念才能掌握它。讓我們來看看這些概念是怎麼應用在我們的伺服器代碼裡的。

我們創建了伺服器,並且向創建它的方法傳遞了一個函數。無論何時我們的伺服器收到一個請求,這個函數就會被調用。

我們不知道這件事情什麼時候會發生,但是我們現在有了一個處理請求的地方:它就是我們傳遞過去的那個函數。至於它是被預先定義的函數還是匿名函數,就無關緊要了。

這個就是傳說中的 回調 。我們給某個方法傳遞了一個函數,這個方法在有相應事件發生時調用這個函數來進行 回調 。

至少對我來說,需要一些功夫才能弄懂它。你如果還是不太確定的話就再去讀讀Felix的博客文章。

讓我們再來琢磨琢磨這個新概念。我們怎麼證明,在創建完伺服器之後,即使沒有HTTP請求進來、我們的回調函數也沒有被調用的情況下,我們的代碼還繼續有效呢?我們試試這個:

var http = require("http");

function onRequest(request, response){
  console.log("Request received.");
  response.writeHead(200,{"Content-Type":"text/plain"});
  response.write("Hello World");
  response.end();
}

http.createServer(onRequest).listen(8888);

console.log("Server has started.");

注意:在 onRequest (我們的回調函數)觸發的地方,我用 console.log 輸出了一段文本。在HTTP伺服器開始工作之後,也輸出一段文本。

當我們與往常一樣,運行它node server.js時,它會馬上在命令行上輸出「Server has started.」。當我們向伺服器發出請求(在瀏覽器訪問http://localhost:8888/ ),「Request received.」這條消息就會在命令行中出現。

這就是事件驅動的異步伺服器端JavaScript和它的回調啦!

(請注意,當我們在伺服器訪問網頁時,我們的伺服器可能會輸出兩次「Request received.」。那是因為大部分伺服器都會在你訪問 http://localhost:8888 /時嘗試讀取 http://localhost:8888/favicon.ico )

伺服器是如何處理請求的

好的,接下來我們簡單分析一下我們伺服器代碼中剩下的部分,也就是我們的回調函數 onRequest() 的主體部分。

當回調啟動,我們的 onRequest() 函數被觸發的時候,有兩個參數被傳入: request 和 response 。

它們是對象,你可以使用它們的方法來處理HTTP請求的細節,並且響應請求(比如向發出請求的瀏覽器發回一些東西)。

所以我們的代碼就是:當收到請求時,使用 response.writeHead() 函數發送一個HTTP狀態200和HTTP頭的內容類型(content-type),使用 response.write() 函數在HTTP相應主體中發送文本「Hello World"。

最後,我們調用 response.end() 完成響應。

目前來說,我們對請求的細節並不在意,所以我們沒有使用 request 對象。

服務端的模塊放在哪裡

OK,就像我保證過的那樣,我們現在可以回到我們如何組織應用這個問題上了。我們現在在 server.js 文件中有一個非常基礎的HTTP伺服器代碼,而且我提到通常我們會有一個叫 index.js 的文件去調用應用的其他模塊(比如 server.js 中的HTTP伺服器模塊)來引導和啟動應用。

我們現在就來談談怎麼把server.js變成一個真正的Node.js模塊,使它可以被我們(還沒動工)的 index.js 主文件使用。

也許你已經注意到,我們已經在代碼中使用了模塊了。像這樣:

var http = require("http");

...

http.createServer(...);

Node.js中自帶了一個叫做「http」的模塊,我們在我們的代碼中請求它並把返回值賦給一個本地變量。

這把我們的本地變量變成了一個擁有所有 http 模塊所提供的公共方法的對象。

給這種本地變量起一個和模塊名稱一樣的名字是一種慣例,但是你也可以按照自己的喜好來:

var foo = require("http");

...

foo.createServer(...);

很好,怎麼使用Node.js內部模塊已經很清楚了。我們怎麼創建自己的模塊,又怎麼使用它呢?

等我們把 server.js 變成一個真正的模塊,你就能搞明白了。

事實上,我們不用做太多的修改。把某段代碼變成模塊意味著我們需要把我們希望提供其功能的部分 導出 到請求這個模塊的腳本。

目前,我們的HTTP伺服器需要導出的功能非常簡單,因為請求伺服器模塊的腳本僅僅是需要啟動伺服器而已。

我們把我們的伺服器腳本放到一個叫做 start 的函數裡,然後我們會導出這個函數。

var http = require("http");

function start(){
  function onRequest(request, response){
    console.log("Request received.");
    response.writeHead(200,{"Content-Type":"text/plain"});
    response.write("Hello World");
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

這樣,我們現在就可以創建我們的主文件 index.js 並在其中啟動我們的HTTP了,雖然伺服器的代碼還在server.js 中。

創建 index.js 文件並寫入以下內容:

var server = require("./server");

server.start();

正如你所看到的,我們可以像使用任何其他的內置模塊一樣使用server模塊:請求這個文件並把它指向一個變量,其中已導出的函數就可以被我們使用了。

好了。我們現在就可以從我們的主要腳本啟動我們的的應用了,而它還是老樣子:

node index.js

非常好,我們現在可以把我們的應用的不同部分放入不同的文件裡,並且通過生成模塊的方式把它們連接到一起了。

我們仍然只擁有整個應用的最初部分:我們可以接收HTTP請求。但是我們得做點什麼——對於不同的URL請求,伺服器應該有不同的反應。

對於一個非常簡單的應用來說,你可以直接在回調函數 onRequest() 中做這件事情。不過就像我說過的,我們應該加入一些抽象的元素,讓我們的例子變得更有趣一點兒。

處理不同的HTTP請求在我們的代碼中是一個不同的部分,叫做「路由選擇」——那麼,我們接下來就創造一個叫做 路由 的模塊吧。

如何來進行請求的「路由」

我們要為路由提供請求的URL和其他需要的GET及POST參數,隨後路由需要根據這些數據來執行相應的代碼(這裡「代碼」對應整個應用的第三部分:一系列在接收到請求時真正工作的處理程序)。

因此,我們需要查看HTTP請求,從中提取出請求的URL以及GET/POST參數。這一功能應當屬於路由還是伺服器(甚至作為一個模塊自身的功能)確實值得探討,但這裡暫定其為我們的HTTP伺服器的功能。

我們需要的所有數據都會包含在request對象中,該對象作為onRequest()回調函數的第一個參數傳遞。但是為了解析這些數據,我們需要額外的Node.JS模塊,它們分別是url和querystring模塊。

url.parse(string).query                                           |           url.parse(string).pathname      |                       |                   |                       |                   |                     - ----http://localhost:8888/start?foo=bar&hello=world                                ---                                       |          |                                 |          |              querystring(string)["foo"]    |                                            |                         querystring(string)["hello"]

當然我們也可以用querystring模塊來解析POST請求體中的參數,稍後會有演示。

現在我們來給onRequest()函數加上一些邏輯,用來找出瀏覽器請求的URL路徑:

var http = require("http");
var url = require("url");

function start(){
  function onRequest(request, response){
    var pathname = url.parse(request.url).pathname;
    console.log("Request for "+ pathname +" received.");
    response.writeHead(200,{"Content-Type":"text/plain"});
    response.write("Hello World");
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

好了,我們的應用現在可以通過請求的URL路徑來區別不同請求了--這使我們得以使用路由(還未完成)來將請求以URL路徑為基準映射到處理程序上。

在我們所要構建的應用中,這意味著來自/start和/upload的請求可以使用不同的代碼來處理。稍後我們將看到這些內容是如何整合到一起的。

現在我們可以來編寫路由了,建立一個名為router.js的文件,添加以下內容:

function route(pathname){
  console.log("About to route a request for "+ pathname);
}

exports.route = route;

如你所見,這段代碼什麼也沒幹,不過對於現在來說這是應該的。在添加更多的邏輯以前,我們先來看看如何把路由和伺服器整合起來。

我們的伺服器應當知道路由的存在並加以有效利用。我們當然可以通過硬編碼的方式將這一依賴項綁定到伺服器上,但是其它語言的編程經驗告訴我們這會是一件非常痛苦的事,因此我們將使用依賴注入的方式較鬆散地添加路由模塊(你可以讀讀Martin Fowlers關於依賴注入的大作<http://martinfowler.com/articles/injection.html>來作為背景知識)。

首先,我們來擴展一下伺服器的start()函數,以便將路由函數作為參數傳遞過去:

var http = require("http");
var url = require("url");

function start(route){
  function onRequest(request, response){
    var pathname = url.parse(request.url).pathname;
    console.log("Request for "+ pathname +" received.");

    route(pathname);

    response.writeHead(200,{"Content-Type":"text/plain"});
    response.write("Hello World");
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

同時,我們會相應擴展index.js,使得路由函數可以被注入到伺服器中:

var server = require("./server");
var router = require("./router");

server.start(router.route);

在這裡,我們傳遞的函數依舊什麼也沒做。

如果現在啟動應用(node index.js,始終記得這個命令行),隨後請求一個URL,你將會看到應用輸出相應的信息,這表明我們的HTTP伺服器已經在使用路由模塊了,並會將請求的路徑傳遞給路由:

bash$ node index.jsRequest for /foo received.About to route a request for /foo

(以上輸出已經去掉了比較煩人的/favicon.ico請求相關的部分)。

行為驅動執行

請允許我再次脫離主題,在這裡談一談函數式編程。

將函數作為參數傳遞並不僅僅出於技術上的考量。對軟體設計來說,這其實是個哲學問題。想想這樣的場景:在index文件中,我們可以將router對象傳遞進去,伺服器隨後可以調用這個對象的route函數。

就像這樣,我們傳遞一個東西,然後伺服器利用這個東西來完成一些事。嗨那個叫路由的東西,能幫我把這個路由一下嗎?

但是伺服器其實不需要這樣的東西。它只需要把事情做完就行,其實為了把事情做完,你根本不需要東西,你需要的是動作。也就是說,你不需要名詞,你需要動詞。

理解了這個概念裡最核心、最基本的思想轉換後,我自然而然地理解了函數編程。

我是在讀了Steve Yegge的大作名詞王國中的死刑之後理解函數編程。你也去讀一讀這本書吧,真的。這是曾給予我閱讀的快樂的關於軟體的書籍之一。

本教程第一部分就先分享到這來,第二部分明日分享。

作者: Manuel Kiessling (http://twitter.com/manuelkiessling)

翻譯: 微博@goddyzhao @MondayChen @GrayZhang (http://otakustay.com/)

有關node.js的文章,優優再推薦一些,點擊下面標題即可閱讀

相關課程推薦✔

想深度全面學習JavaScript的同學,歡迎了解優才學院JavaScript全棧高級直播課程。本套JS全棧高級課程專為有一定前端基礎的開發者打造。主講內容:JavaScript前端、Nodejs後端、HTML5 移動端、React Native原生等技術。

回復「JS大綱」查看課程大綱

課程諮詢QQ:1442553296 / 2081411382

相關焦點

  • 10+ 最佳的 Node.js 教程結合實例
    我們所覆蓋的指南將包括針對初學者的Node.js、中級指南,同時還有教你怎樣構建複雜的Node.js項目。對於完全的Node.js初學者,  在深入挖掘本文章後續提到的學習項目之前,一步步按照airpair.com上面入門指南的要點 或 Node.js入門指南 之類的文章學習是不錯的選擇。
  • Node.js 學習資料和教程(值得收藏)
    模塊排行榜,方便找出你想要的模塊nodejs多線程,真正的非阻塞淺析nodejs的buffer類利用libuv編寫異步多線程的addon實例Node.js中exports與module.exports篇用node+express搭建多人博客教程系列Node.js靜態文件伺服器實戰人人和微博登錄模塊的實現《京JS》會議 & V8上的JS優化
  • 專門針對初學者的Node.js教程
    Node.js的教程並不缺乏,但有大部分教程針對已有Node.js基礎的開發者。「我已下載了Node.js,可我如何開始呢?」以下教程是專門針對Node.js初學者,文中將通過實例分享,一步步教你如何開始Node.js之旅。  什麼是Node.js?
  • 基於NodeJS從零構建線上自動化打包工作流
    Node.js 使用事件驅動,非阻塞I/O 模型而得以輕量和高效,非常適合在分布式設備上運行數據密集型的實時應用。所以作為一名優秀的前端工程師,非常有必要了解和掌握Node.js。筆者接下來將通過對H5-Dooring項目中的實時在線下載代碼功能來帶大家掌握如何從零構建線上自動化打包工作流。
  • nodejs的調試debug
    nodejs也不例外。今天我們來詳細介紹一下如何調試nodejs程序。開啟nodejs的調試還記得之前我們講到的koa程序嗎?本文將會以一個簡單的koa服務端程序為例,來展開nodejs的調試。要想運行上面的程序,我們需要執行node app.js。這會執行app.js但是並不會開啟調試功能。怎麼進行調試呢?我們需要加上 –inspect 參數:node --inspect app.js上面的代碼將會開啟nodejs的調試功能。
  • nodejs windows環境下搭建
    本文為初學者介紹Node JS在windows環境下的搭建。瀏覽器打開http://nodejs.org/ ,下載node.js運行環境安裝,如下圖:點擊downloads,進入下載列表;並從可選擇安裝的列表中找符合windows環境的安裝文件下載之後雙擊安裝,有默認路徑,我的安裝路徑change為D盤了,其他選項選擇默認即可,一直next就ok。
  • 初學者怎麼學動漫繪畫?動漫初學者入門教程
    初學者怎麼學動漫繪畫?動漫初學者入門教程!零基礎小白學動漫繪畫,通常是比較困難的,很多時候都是靠一股熱血支撐,但由於種種原因, 那種激情就會消退,久而久之就學不下去了。面對這種情況,小白們也很無奈,所以今天,小編給小白們送福利啦!告訴你零基礎小白學動漫繪畫應該怎麼學。
  • centos7編程實踐:安裝nodejs
    由於最近項目的需要,我需要在centos7上安裝nodejs,故總結這份教程,希望能幫助需要的同學。一、nodeJS簡介1、Nodejs是什麼?Nodejs是基於V8引擎,V8是Google發布的開源JavaScript引擎,本身就是用於Chrome瀏覽器的js解釋部分,但是Ryan Dahl 這哥們,鬼才般的,把這個V8搬到了伺服器上,用於做伺服器的軟體。
  • 吉他新手教學入門教程,初學者怎麼學吉他?
    吉他新手教學入門教程,初學者怎麼學吉他?吉他教學入門、吉他新手入門教學、吉他教學入門教程、初學者怎麼學吉他?【教程】吉他自學教程,讓文藝與你同在!我相信,很多人心中都有一個吉他夢當你在學校的新年晚會上看著你的某個同學抱著一把YAMAHA迎接著臺下的尖叫當你在夏天清晨的半睡半醒時刻聽著鄰家的《天空之城》響起當你在酒吧聽著《安河橋》...
  • 知錯能改的nodejs之父
    而隨之帶來的就是在2009年,伺服器端的node誕生了,而這個語言的創造者就是今天我們要介紹的主人公——nodejs之父-Ryan Dahl。Ryan Dahl出生在美國加利福尼亞洲的聖地牙哥。他的家庭環境很好,小的時候,他的父母就給他買了一臺Apple IIc電腦。
  • Node v0.12.3 穩定版發布
    /dist/v0.12.3/node-v0.12.3.tar.gzMacintosh Installer (Universal): http://nodejs.org/dist/v0.12.3/node-v0.12.3.pkgWindows Installer: http://nodejs.org/dist/v0.12.3/node-v0.12.3-x86.msi
  • Node v0.11.3 (Unstable) 發布
    /dist/v0.11.3/node-v0.11.3.tar.gzMacintosh Installer (Universal): http://nodejs.org/dist/v0.11.3/node-v0.11.3.pkgWindows Installer: http://nodejs.org/dist/v0.11.3/node-v0.11.3-x86.msi
  • Nodejs cms 內容管理框架 DoraCMS2.0 部署教程
    git clone https://github.com/doramart/DoraCMS.git -b 2.0.0beta2、安裝nodejs,mongodb。無密碼啟動mongodb (這部分不再過多介紹,在DoraCMSv1.0的部署教程中已經做了詳細介紹,或者自行百度)註: DoraCMS2.0需要安裝最新版本node,mongodb3.0及以上。3、安裝依賴。
  • 在macOS Catalina 上如何安裝 NodeJS
    訪問 NodeJS 的官方網站:https://nodejs.org/en/ 然後下載為大多數用戶推薦的版本。運行剛剛下載的 node-v****.pkg 文件。Catalina");保存 helloWorld.js 文件後,打開終端然後切換到存儲JS文件的目錄:cd PATH_TO_YOUR_FOLDER_CONTANING_THE_JS_FILE輸入如下命令運行 helloWorld.js 文件:node
  • 致泰語初學者:實用泰語入門教程介紹
    《基礎泰語(一)》《基礎泰語1》系統地涵蓋了泰語學習所應掌握的基礎知識和技能。該教材從輔音、元音以及聲調的讀法和寫法入手,發展為詞的拼讀和拼寫,繼而逐步轉入短語、句子和短文的學習,還給每一章節精心設計了全面的拼讀和拼寫練習,使得泰語初學者輕鬆入門,循序漸進。
  • 以太坊Truffle框架搭建一氣呵成無坑版教程
    本文約1600字+,閱讀(觀看)需要15分鐘Truffle框架搭建的教程網上也有好多,但是隨著truffle版本的更新,truffle.js改名truffle-config.js、truffle命令升級、truffle與testrpc埠不一致、瀏覽器錢包插件等問題,導致原有的教程不再適用
  • ECMAScript 6 入門教程
    》是一本開源的 JavaScript 語言教程,全面介紹 ECMAScript 6 新引入的語法特性。本書覆蓋 ES6 與上一個版本 ES5 的所有不同之處,對涉及的語法知識給予詳細介紹,並給出大量簡潔易懂的示例代碼。本書為中級難度,適合已經掌握 ES5 的讀者,用來了解這門語言的最新發展;也可當作參考手冊,查尋新增的語法點。如果你是 JavaScript 語言的初學者,建議先學完《JavaScript 語言入門教程》。
  • 抖音入門基礎知識篇 抖音初學者入門教程
    1、保證直播時長和頻次規律 這是做抖音直播最基本的要求。 更多抖音入門知識加我微信領取,小編精心整理了這套針對零基礎學員的直播課程。
  • 對初學者的簡單解釋!什麼是伺服器端JavaScript Node.js?
    缺點1:如果要 需要使用Node.js兼容伺服器的租賃伺服器上使用Node.js ,則在明顯的情況下,您需要使用VPS伺服器,或者即使可以使用它,響應速度也很慢。你呢 Node.js用戶以Heroku和OpenShift等伺服器而聞名,但由於它們是海外服務,因此需要英語技能。 缺點2:您需要在伺服器上設置Node.js。
  • 首發:適合初學者入門人工智慧的路線及資料下載
    本文為AI入門提供了一個簡易的學習路線,並提供了代碼和數據集下載。(黃海廣)一、前言AI以及機器學習入門,初學者遇到的問題非常多,但最大的問題就是:資料太多!!!看不完!!!不知道如何取捨!!!人的精力有限!!!