Nodejs學習筆記之入門篇,nodejs學習筆記

來源:互聯網
上載者:User

Nodejs學習筆記之入門篇,nodejs學習筆記

分享第一篇,關於 NodeJS —— Javascript 的常用知識以及如何從 Javascript 開發人員過渡到 NodeJS 開發人員(不會介紹具體的架構)。在讀本文前,希望你對 javascript 有一些初步的認識。

Javascript 是一門原型模型的解釋型語言。解釋型將在後面的 NodeJS 裡面討論,原型鏈是 ES6 之前的 Javascript 的物件導向的實現方式之一,在 ES6 中支援的 class 增加了一種新的實現方式。在 Javascript 裡面所有東西都是對象,包括 “類”。接觸過 ruby/python 的元編程的可能會覺得這個很熟悉,Javascript 也很容易是實現出動態產生類的方法。

1. 基於原型鏈實現的簡單的“類”

var Person = function(name){ this.name = name;};Person.staticSay = function(name){ console.log('Hello ' + name);};Person.prototype.sayHi = function(){ Person.staticSay(this.name);}

提一些常見的規範,例如 Javascript 中所有的方法都是駝峰命名,優先使用單引號,兩個空格等等,更多的規範可以參考 https://github.com/airbnb/javascript。

代碼中的staticSay為靜態方法,即只能通過 Person.staticSay來調用。 當上面的 Person 產生執行個體的時候,例如 var vincent = new Person('vincent');的時候,vincent會自動繼承 Person.prototype 的所有方法(代碼中的 this 指代的是當前上下文,即上文中的 vincent)。

同時也可以動態為對象 vincent 添加方法,例如如下代碼:

var vincent = new Person('vincent')vincent.tellName = function(){ console.log('Hi, i\'m am' + this.name)};

然後當你需要類比繼承的時候,就需要在 prototype 上下功夫。例如下面使用 Worker.prototype = new Person() 來實現,new Person() 返回的執行個體對象帶著的所有方法、屬性都被賦給了 prototype,變相類比了繼承。這種方式最終一層層的往上找 prototype 裡面的內容(因為每個執行個體具有的方法都在 prototype 裡面,往上直到 Object)。當然也可以通過遍曆來進行對 prototype 賦值來類比繼承。

2. 環境切換

上下文最直觀的表現就是代碼塊中的 this,通常在物件導向的編程中用到,來指代當前“類”產生的對應執行個體,與其他語言的 self一致。

繼續用上文中的例子,上文中已經實現了一個 Person.prototype.sayHi方法,現在我有一個新的對象,代碼如下:

var Cat = function(name){ this.name = name;}var c = new Cat('tomcat');

如果某天突然異想天開希望這隻貓像人一樣介紹他自己怎麼辦,他自己沒有 sayHi 這個方法。但是可以通過 console.log(Person.prototype.sayHi)是可以拿到人類的 sayHi 方法的,怎麼讓貓也可以使用呢?

Javascript 有兩個方法,call 和 apply,他們的區別就是參數不同(自行Google),作用是用來切換上下文。簡單說就是可以把 Person.prototype.sayHi這個函數中的 this 變成其他對象。使用方式: Person.prototype.sayHi.call(c)。

這個實用嘛?例如如下情境:

var doSomething = function(){ var persons = arguments;};

上面的函數中,通過關鍵字 arguments擷取所有的參數來支援不定數量的參數。現在我們希望對 persons用一些原屬於 Array 類型的方法,如何?呢?這裡就可以用環境切換來實現:

var doSomething = function(){ var persons = arguments; // 使用 Array 的 slice 方法,將 arguments 對象轉變為 Array 執行個體 var persons_arr = Array.prototype.slice.call(arguments);};

3. 閉包

先來段常見的代碼

for (var i = 0; i < 3; i ++){ setTimeout(function(){  console.log(i); }, i)}

這個會輸出什麼結果呢?依次輸出 0 1 2 ?實際情況是,當 setTimeout第一次執行回調的時候,for 迴圈已經結束了,也就是說此時的 i 已經是 3 了,導致最終的輸出結果是 3 3 3。

當你需要保護某一個變數,使得他不被外圍的代碼所影響的時候,你可能就需要考慮下閉包 —— 一個封閉的範圍的代碼塊。

for (var i = 0; i < 3; i ++){ +function(i){  setTimeout(function(){   console.log(i);  }, i) }(i)}

咦, +是幹嘛的,有沒有其他方式實現,請自行Google。閉包內的 i 的範圍是一個封閉的範圍,所以最終 閉包內的 i 一直沒有被外面的執行改變,所以可以成功的輸出 0 1 2。

簡單的介紹了 javascript 部分特性,關鍵字 原型鏈、call 和 apply、arguments 關鍵字,更多的建議可以看看例如權威指南這樣的書,或者快速瞭解下基本的類型以及每個類型有的方法。有一些比較神奇的代碼,例如獲得當前的代碼的字串,然後進行處理得到自己想要的內容,使用 getter 和 setter 在使用者對對象屬性擷取或者賦值的時候做一些特殊的操作等等。

4. NodeJS 和 Javascript 的開發區別

這塊主要介紹 require 載入的基礎知識,首先先介紹一些代碼:

// a.jsmodule.exports = { name: "a", doSomething: function(){  return "something"; }}// b.jsvar a = require('./a')global.a_name = a.name;// c.jsrequire('./b');console.log(a_name) // 執行後列印 a 

當我們執行 node c.js的時候發生了什嗎?

require是 nodes 關鍵字,雖然 NodeJS 是以非同步著稱,但是他的 require都是阻塞的。否則就會出現還沒有載入其他模組,已經開始執行下面的代碼的情況。

require.resolve()方法是用來找出你所引用的檔案的實際路徑,找出後 Nodejs 會在 require.cache裡面尋找是否有緩衝,沒有的話則會讀取檔案然後解析,所以通常情況下,一個 js 檔案裡面的執行的代碼只會在第一次被 require 的時候被執行。(tip. require.cache 如果有需要的話是可以手動刪除一些東西的,然後可以某種程度上可以執行多次)

當 b.js 開始執行的時候,他需要先載入 a.js,module.exports告訴 Nodejs 這個檔案對外暴露寫什麼,例如 a.js 暴露的是一個對象,包含 name 屬性和 doSomething 方法。然後 b.js 中的 a 變數其實就是這個對象。

執行完擷取 a.js 後,繼續回到 b.js ,global.a_name 相當於聲明了一個全域變數,這個和前端中的 window.a_name = a.name 效果類似。

最終過程完成,c.js 執行輸出值。

5. 非同步底層原理

NodeJS 很容易給人一種使用上的錯覺,就是寫了很久都可能不知道底層的非同步是怎麼實現的。(下面的理解主要來自於對 python3.4 中的 asyncio 的理解,如有錯誤歡迎指出)。

NodeJS 底層的 libev 分別在 Window 下使用 IOCP 和 *nix 下使用基於 AIO 的 libeio 來實現非同步。通過系統層面的技術,最後達到一個目的,就是應用程式發起一個非同步請求,最終在系統執行完後,系統通知應用程式處理完成。在這個過程中,應用程式可以將之前的處理掛起/推入線程池中等待執行,而應用程式在此期間可以執行其他任務。

整個的運行通過系統層面的事件迴圈來進行運作。例如 Python 提供了類似於 run_until 以及 run_forever 的這樣的方法,保證在非同步執行之前程式不會結束運行。將整個非同步想象成一個一直在運作的車間,車間裡面的機器負責查看包裹並蓋章這樣的操作,工人拿到了一個包裹,然後貼上相應的標籤後放進去,等車間處理完後再交還給工人,工人根據包裹上他之前貼上的標籤和被車間貼上的標籤,進行下一步的處理。工人無需等待包裹檢查完畢才能進行下一個,他只需要接受簡單處理,然後放入車間進行檢查。然後等某個時間車間返回給他某個包裹,他再去進行下一步的操作。

目前主要還是只介紹了一些語言層面的知識,但是只有這些距離開發一個完整的 web 還有一些距離,將在後面繼續介紹。包括 Redis,Nginx,測試驅動等等。

以上所述就是本文的全部內容了,希望大家能夠喜歡。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.