Node.js基礎教程筆記

第一章 簡介

1.1Node.js 是什麼

CommonJS 規範

一個單獨的文件就是一個模塊。加載模塊使用require方法,該方法讀取一個文件並執行,最後返回文件內部的exports對象。html

console.log("evaluating example.js");

var invisible = function () {
  console.log("invisible");
}

exports.message = "hi";

exports.say = function () {
  console.log(message);
}

使用require方法,加載example.js。node

var example = require('./example.js');

這時,變量example就對應模塊中的exports對象,因而就能夠經過這個變量,使用模塊提供的各個方法。git

{
  message: "hi",
  say: [Function]
}

require方法默認讀取js文件,因此能夠省略js後綴名。github

var example = require('./example');

js文件名前面須要加上路徑,能夠是相對路徑(相對於使用require方法的文件),也能夠是絕對路徑。若是省略路徑,node.js會認爲,你要加載一個核心模塊,或者已經安裝在本地 node_modules 目錄中的模塊。若是加載的是一個目錄,node.js會首先尋找該目錄中的 package.json 文件,加載該文件 main 屬性提到的模塊,不然就尋找該目錄下的 index.js 文件。web

下面的例子是使用一行語句,定義一個最簡單的模塊。express

// addition.js
exports.do = function(a, b){ return a + b };

上面的語句定義了一個加法模塊,作法就是在exports對象上定義一個do方法,那就是供外部調用的方法。使用的時候,只要用require函數調用便可。npm

var add = require('./addition');

add.do(1,2)
// 3

再看一個複雜一點的例子。編程

// foobar.js

function foobar(){
        this.foo = function(){
                console.log('Hello foo');
        }

        this.bar = function(){
                console.log('Hello bar');
        }
}
exports.foobar = foobar;

調用該模塊的方法以下:json

var foobar = require('./foobar').foobar,
    test   = new foobar();

test.bar(); // 'Hello bar'

有時,不須要exports返回一個對象,只須要它返回一個函數。這時,就要寫成module.exports。數組

module.exports = function () {
  console.log("hello world")
}

1.2Node能作什麼?

  • 具備複雜邏輯的網站;
  • 基於社交網絡的大規模 Web 應用;
  • Web Socket 服務器;
  • TCP/UDP 套接字應用程序; *
  • 命令行工具;
  • 交互式終端程序;
  • 帶有圖形用戶界面的本地應用程序;
  • 單元測試工具;
  • 客戶端 JavaScript 編譯器。

1.3異步式 I/O 與事件驅動

  • 異步式 I/O: 跳過I/O直接運行下一步,再也不等待I/O處理結果
  • 事件驅動:事件隊列,程序執行的時候進入事件循環來執行下一個事件

1.4Node.js性能

比PHP性能要高不少

1.5JavaScript簡史

第二章 安裝和配置Node.js

第三章 快速入門

  • node helloworld.js:執行js腳本

  • node 的 REPL 模式(同Python的Shell交互模式)

3.1建立Http服務器

//app.js 

var http = require('http'); 


http.createServer(function(req, res) { 

 res.writeHead(200, {'Content-Type': 'text/html'}); 

 res.write('

<h1>Node.js</h1>

'); 

 res.end('

<p>Hello World</p>

'); 

}).listen(3000); 

console.log("HTTP server is listening at port 3000.");

3.2使用supervisor

  • 安裝

    $ npm install -g supervisor

  • 使用

    $ supervisor app.js

  • 做用:開發時修改代碼後會自動終止腳本,而後從新啓動,方便調試。

3.3異步式 I/O 與事件式編程

  • 異步I/O

    • 優勢:單線程減小開銷
    • 缺點:編程思惟獨特,難以適應
  • 回調函數:不鼓勵用同步I/O
  • 事件循環機制:Node.js 程序由事件循環開始,到事件循環結束,全部的邏輯都是事件的回調函數,因此 Node.js 始終在事件循環中,程序入口就是事件循環第一個事件的回調函數。事件的回調函數在執行的過程當中,可能會發出 I/O 請求或直接發射(emit)事件,執行完畢後再返回事件循環,事件循環會檢查事件隊列中有沒有未處理的事件,直到程序結束。

3.4模塊和包

  • 二者沒有本質區別
  • 文件和模塊一一對應,一個Node.js文件就是一個模塊

加載:

  • require 用於從外部獲取一個模塊的接口,即所獲取模塊的 exports 對象。
  • exports 是模塊公開的接口

例子:

//module.js 

var name; 

exports.setName = function(thyName) { 
 name = thyName; 
}; 

exports.sayHello = function() { 
 console.log('Hello ' + name); 
};

在同一目錄下建立 getmodule.js,內容是:

//getmodule.js 
var myModule = require('./module'); 
myModule.setName('BYVoid'); 
myModule.sayHello();

運行node getmodule.js,結果是:

Hello BYVoid

單次加載

這點和對象不同,不管調用多少次 require,得到的模塊都是同一個

//loadmodule.js 
var hello1 = require('./module'); 
hello1.setName('BYVoid'); 
var hello2 = require('./module'); 
hello2.setName('BYVoid 2'); 
hello1.sayHello();

輸出結果:

Hello BYVoid 2

結果被後者覆蓋了。

覆蓋exports

//singleobject.js 
function Hello() { 
 var name; 
 this.setName = function (thyName) { 
 name = thyName; 
 }; 
this.sayHello = function () { 
 console.log('Hello ' + name); 
 }; 
}; 
exports.Hello = Hello; 

//簡化後:module.exports = Hello;

簡化前:

require('./singleobject').Hello

簡化後能夠直接獲取對象:

//gethello.js 
var Hello = require('./hello'); 
hello = new Hello(); 
hello.setName('BYVoid'); 
hello.sayHello();

exports本是就是一個空對象,本質上是經過閉包來創建一個有限的的訪問接口。(很簡單卻想了好久~)

建立包

commonJS規範以下:

  • package.json 必須在包的頂層目錄下;
  • 二進制文件應該在 bin 目錄下;
  • JavaScript 代碼應該在 lib 目錄下;
  • 文檔應該在 doc 目錄下;
  • 單元測試應該在 test 目錄下。

package.jason

Node.js 在調用某個包時,會首先檢查包中 package.json 文件的 main 字段,將其做爲包的接口模塊,若是 package.json 或
main 字段不存在,會嘗試尋找 index.js 或 index.node 做爲包的接口。

  • name:包的名稱,必須是惟一的,由小寫英文字母、數字和下劃線組成,不能包含空格。
  • description:包的簡要說明。
  • version:符合語義化版本識別①規範的版本字符串。
  • keywords:關鍵字數組,一般用於搜索。
  • maintainers:維護者數組,每一個元素要包含 name、email (可選)、web (可選)字段。
  • contributors:貢獻者數組,格式與maintainers相同。包的做者應該是貢獻者數組的第一個元素。
  • bugs:提交bug的地址,能夠是網址或者電子郵件地址。
  • licenses:許可證數組,每一個元素要包含 type (許可證的名稱)和 url (連接到許可證文本的地址)字段。
  • repositories:倉庫託管地址數組,每一個元素要包含 type (倉庫的類型,如 git )、url (倉庫的地址)和 path (相對於
    倉庫的路徑,可選)字段。
  • dependencies:包的依賴,一個關聯數組,由包名稱和版本號組成。

例子:

{ 
 "name": "mypackage", 
 "description": "Sample package for CommonJS. This package demonstrates the required 
elements of a CommonJS package.", 
 "version": "0.7.0", 
 "keywords": [ 
 "package", 
 "example" 
 ], 
 "maintainers": [ 
 { 
 "name": "Bill Smith", 
 "email": "bills@example.com", 
 } 
 ], 
 "contributors": [ 
 { 
 "name": "BYVoid", 
 "web": "http://www.byvoid.com/" 
 } 
 ], 
 "bugs": { 
 "mail": "dev@example.com", 
 "web": "http://www.example.com/bugs" 
 }, 
 "licenses": [ 
 { 
 "type": "GPLv2", 
 "url": "http://www.example.org/licenses/gpl.html" 
 } 
 ], 
 "repositories": [ 
 { 
 "type": "git", 
 "url": "http://github.com/BYVoid/mypackage.git" 
 } 
 ], 
 "dependencies": { 
 "webkit": "1.2", 
 "ssl": { 
 "gnutls": ["1.0", "2.0"], 
 "openssl": "0.9.8" 
 } 
 } 
}

包管理

npm:

npm [install/i] [package_name]
  • 本地模式:默認方法,存放當前目錄下
  • 全局模式:減小重複副本

    npm [install/i] -g [package_name]

  • 建立全局連接:把全局包當成本地包來用

    $ npm link express
    ./node_modules/express -> /usr/local/lib/node_modules/express

使用 node-inspector 調試 Node.js

npm install -g node-inspector //安裝insepctor
node --debug-brk=5858 debug.js //連接服務器
$ node-inspector//啓動
 http://127.0.0.1:8080/debug?port=5858 //瀏覽器中打開!
相關文章
相關標籤/搜索