Node.js 十問

簡評:作者在一次技術分享中提了 10 個問題,結果在場的很多開發者不能準確的說出答案,看看這 10 個問題你都了解嗎?

什麼是調用堆棧,他是 V8 的一部分嗎?

調用棧是 V8 的一部分。 調用棧在 V8 中是一個數據結構,用於追蹤方法的調用。 每次調用一個函數時,V8 都會在調用棧中引用該函數。並且每次調用其他函數都會如此(包括遞歸調用的函數)。

當函數調用結束時 V8 將 Pop 該函數並且在函數調用處返回他的值。

了解這個很重要,因為每一個 Node 進程只會有一個調用棧,如果你的調用棧處於繁忙,那麼你的這個 Node 進程便處於繁忙。

什麼是事件循環?他是 V8 的一部分嗎?

事件循環處在下圖中的哪個模塊?

事件循環是由 libuv 庫提供的,它不是 V8 的一部分。

event loop 用於處理外部事件並且將其轉化為回調,它會從事件隊列中選擇事件並將其事件回調 push 到調用棧中。

事件循環位於這張照片的中間,並且像一個組織者一樣。當V8調用堆棧為空時,事件循環可以決定下一步執行什麼。

當調用棧和 event loop 為空的時候,Node 會做些什麼?

它只會退出。

當您運行 Node 程序時,Node 將自動啟動事件循環,當該事件循環處於空閑狀態並且沒有任何其他操作時,該進程將退出。為了保持 Node 進程的運行,您需要在某個事件隊列中放置某些東西。例如,當您啟動計時器或 HTTP 伺服器時,相當於告訴事件循環繼續運行並檢查這些事件。

除了 V8 和 Libuv,Node 還有哪些外部依賴?

以下是 Node 進程用到的依賴庫:

  • http-parser
  • c-ares
  • OpenSSL
  • zlib

他們都是 Node 所用到的依賴庫,他們有自己的源碼,協議。 Node 只是使用了他們。所以如果你正在進行數據壓縮並且報錯了,不要怪 Node。

如果沒有 V8 可以運行 Node嗎?

這可能是一個棘手的問題。您需要一個 VM 來運行 Node 進程,但 V8 不是唯一可以使用的VM。你還可以使用 Chakra。

module.exports 和 exports 有什麼區別?

你可以使用 module.exports 導出模塊的 API,當然你也可以使用 exports。

module.exports.g = ... // Okexports.g = ... // Okmodule.exports = ... // Okexports = ... // Not Ok

export 只是 module.exports 的引用或者別名。真正起作用的是 module.exports ,如果給 exports 重新賦值,那麼 exports 和 module.exports 將不再有關係。

為什麼定義的頂級變數不是全局的?

如果你有 module1 定義了頂級變數 g:

// module1.jsvar g = 42;

如果在 module2 require module1 並嘗試訪問變數 g,你會得到 g is not defined 的錯誤。

但是如果你在瀏覽器中執行相同的操作,則可以訪問所有 scirpt 的頂級變數(已經定義過的),

每個 Node 文件都有一個自己的IIFE(即時調用函數表達式)。在 Node 文件中聲明的所有變數都被限定在 IIFE 中。

相關問題:運行如下 Node 文件輸出的是什麼?

// script.jsconsole.log(arguments);

你會看到一些參數:

因為 Node 執行的是一個函數。Node 用一個函數包裝你的代碼,該函數顯式地定義了如上五個參數。

exports,require 和 module 這些對象都可以在每個文件中全局可用,但在每個文件中都是不同的。這是如何做到的?

當您需要使用 require 對象時,您只需直接使用它,就像它是一個全局變數一樣。但是,如果您在兩個不同的文件中檢查他們,您將看到兩個不同的對象。怎麼會這樣?

同樣是因為 IIFE:

如上所示,IIFF 將傳遞給您的代碼以下五個參數:exports,require,module,__filename 和__dirname。當您在 Node 中使用這些變數時,這五個變數似乎是全局變數,但它們實際上只是函數參數。

什麼是模塊循環依賴:

如果你有一個 module1,module1 require module2 和 module2 反過來require module1,會發生什麼?會報錯嗎?

// module1require("./module2");

// module2require("./module1");

這樣並不會報錯。Node 允許這種操作。

所以 module1 require module2,但是由於module2 require module1 (此時 module1 還沒有完成),module1 只會得到 module2 的部分版本。

這樣會被警告。

什麼時候可以使用文件系統 *Sync(如readFileSync)

Node 中的每個 fs 方法都具有同步版本。為什麼要使用同步方法而不是非同步?

有時使用同步方法是個很好的選擇。例如,它可以在伺服器仍在載入的初始化中使用。使用同步方法是可以接受的,只要你使用同步方法是一次性的事情(像 Http 請求這種多次回調的肯定是錯誤的)。

原文:You don』t know Node

推薦閱讀:新 V8 即將推出,和 Node.js 性能變化

推薦閱讀:

如何持久編程?
想設計一個簡單的程序向女生表白,有什麼好的想法?

TAG:Nodejs | JavaScript | 编程 |