<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [TOC] # 簡介 簡單的說 Node.js 就是運行在服務端的 JavaScript。 Node.js 是一個基于Chrome JavaScript 運行時建立的一個平臺。 Node.js是一個事件驅動I/O服務端JavaScript環境,基于Google的V8引擎,V8引擎執行Javascript的速度非常快,性能非常好。 > [Node.js ECMAScript兼容性表](https://node.green/) > [Node.js 中 LTS 和 Current 的有啥區別?](https://zhuanlan.zhihu.com/p/43213315) # Node 架構圖 Node.js主要有兩種類型的組件 - 核心組件和node.js API(模塊)。 核心組件使用C和C ++編寫,node.js API使用JavaScript編寫。 Node.js架構圖如下: ![](https://img.kancloud.cn/2d/f6/2df6feeedebfc6a8c510b9dc213ea189_660x281.png) ## Node.js API 這些是用 JavaScript 編寫的,并直接暴露給外部世界,以與 Node.js 內部組件進行交互。 Node.js Binding 是核心API,它將JavaScript與C / C ++庫綁定。 ## C/C++ Add-ons 您還可以使用C / C ++開發 Node.js 插件(Add-ons)以使用Node.js。 ## V8 https://v8.dev/ 它是 Google 的開源 JavaScript 引擎, 用C ++ 編寫。 實際上,它是一個 JavaScript VM,它不是解釋 JS 代碼 而是將 JavaScript 代碼編譯為本機代碼。 它是 JavaScript 中最快的JIT(Just-In-Time)編譯器。 ## Libuv ![libuv](https://box.kancloud.cn/204fa36e4858953873b10854a70e6078_1024x768.png) 它是一**多平臺支持 C++ 庫**,它封裝了 Libev、Libeio 以及 IOCP,保證了跨平臺的通用性。它負責處理 Node.js 中的線程池,事件循環和異步 I/O 操作。 在 Node.js 中,阻塞 I/O 操作被委托給 Libuv 模塊,Libuv 模塊具有固定大小的 C++ 線程池來處理這些操作。 完成這些操作后,會通知事件循環。 想深入的話:推薦書籍:《Node.js:來一打C++擴展》 >[兄 déi,libuv 了解一下](https://zhuanlan.zhihu.com/p/50497450) ## C-ares 一個用于并行處理異步DNS請求、名稱解析和多個DNS查詢的 C 庫。 ## http_parser 一個用于解析HTTP請求和響應的C庫。 ## OpenSSL 一個用于實現安全套接字層(SSL v2/v3)和傳輸層安全性(TLS v1)協議的C庫。 它還提供了所有必要的加密方法,如哈希,密碼,解密,簽名和驗證等。 ## Zlib 一個用于數據壓縮和解壓縮的C庫。 # node 是單線程的嗎? 提到 node,我們就可以立刻想到單線程、異步 IO、事件驅動等字眼。首先要明確的是 node 真的是單線程的嗎,如果是單線程的,那么異步 IO,以及定時事件(setTimeout、setInterval 等)又是在哪里被執行的。 Node 中最核心的是 v8 引擎,在 Node 啟動后,會創建 v8 的實例,這個實例是多線程的。包括: ``` 主線程:編譯、執行代碼。 編譯 / 優化線程:在主線程執行的時候,可以優化代碼。 分析器線程:記錄分析代碼運行時間,為 Crankshaft 優化代碼執行提供依據。 垃圾回收的幾個線程。 .... ``` 我們平時所說的**Node 是單線程的指的是 JavaScript 的執行是單線程的(開發者編寫的代碼運行在單線程環境中)**。Javascript 的宿主環境,無論是 Node 還是瀏覽器都是多線程的。 * 其他異步 IO 和事件驅動相關的線程通過 libuv 來實現內部的線程池和線程調度。 解釋:nodejs 執行 異步 IO 等操作時,會先從 js 代碼通過 **node-bindings** 調用到 C/C++ 代碼,然后通過 C/C++ 代碼封裝一個叫 “請求對象”(**傳入的參數和回調函數封裝成一個請求對象**) 的東西交給 `libuv`,給 `libuv` 執行以及執行完實現回調。 * libv 中存在了一個 Event Loop,通過 Event Loop 來切換實現類似于多線程的效果。 Event Loop 是 libuv 的核心所在,上面我們提到 js 會把回調和任務交給 libuv,**libuv 何時來調用回調就是 Event Loop 來控制的**。 簡單的來講 Event Loop 就是維持一個執行棧和一個事件隊列,當前執行棧中的如果發現異步 IO 以及定時器等函數,就會把這些異步回調函數放入到事件隊列中。當前執行棧執行完成后,從事件隊列中,按照一定的順序執行事件隊列中的異步回調函數。 ![](https://img.kancloud.cn/77/ec/77ec5f5a4de27096dc47a49e7d1aa7d6_474x336.png) 上圖中從執行棧,到事件隊列,最后事件隊列中按照一定的順序執行回調函數,整個過程就是一個簡化版的 Event Loop。此外回調函數執行時,同樣會生成一個執行棧,在回調函數里面還有可能嵌套異步的函數,也就是說執行棧存在著嵌套。 也就是說 node 中的單線程是指 js 引擎只在唯一的主線程上運行,其他的異步操作,也是有獨立的線程去執行,**通過 `libv` 的 Event Loop 實現了類似于多線程的上下文切換以及線程池調度**。線程是最小的進程,因此 node 也是單進程的。這樣就解釋了為什么 node 是單線程和單進程的。 > [nodejs 真的是單線程嗎?](https://segmentfault.com/a/1190000014926921) # Node.js的文件路徑 > * `__dirname` : 獲得當前執行文件所在目錄的完整目錄名 > * `__filename` : 獲得當前執行文件的帶有完整絕對路徑的文件名 > * `process.cwd()`:獲得當前執行node命令時候的文件夾目錄名 > * `./`:不使用 `require` 時候,`./` 與 `process.cwd()` 一樣,使用 `require` 時候,與 `__dirname` 一樣 只有在?`require()`?時才使用相對路徑`(./, ../)`的寫法,其他地方一律使用絕對路徑,如下: ``` // 當前目錄下 path.dirname(__filename) + '/path.js'; // 相鄰目錄下 path.resolve(__dirname, '../regx/regx.js'); ``` 最后看看改過之后的結果,不會報錯找不到文件了,不管在哪里執行這個腳本文件,都不會出錯了,防止以后踩坑。 # global 模塊 Node 中我們有 `global` 對象可以進行掛載,很多共用的屬性就可以掛載到 `global` 對象上了,本身它自己也擁有很多的屬性。 ![](https://box.kancloud.cn/3f178b6bb1ad8a70894e73cce10bc9b0_845x339.png) ## `global` 全局命名空間,通過 `global` 定義的變量,在任何地方都可以使用,類似于瀏覽器端定義在全局范圍中的變量。 ``` // foo.js global.foo = 'hello'; ``` ``` // bar.js require('./foo'); console.log(foo); //hello ``` 定義在 `global` 上面的變量,不需要在模塊中通過 `exports` 輸出,其他模塊中也能使用。 ## `__dirname` `__dirname` 實際上不是一個全局變量,在命令行模式下直接調用會提示 `__dirname` 未定義,但是在模塊中可以直接使用,返回當前腳本執行的目錄。 ``` console.log(__dirname); ``` ## `__filename` 返回當前執行代碼文件的名稱(包含文件的絕對路徑)。和 `__dirname` 一樣,`__filename` 也不是一個全局變量,但在模塊中可以直接使用。 ``` console.log(__filename); ``` `__filename` 返回的是包含路徑的文件名。 # node 中的 `this` 在 nodejs 中的 `this` 而非 javascript 中的 `this`,nodejs 中的 `this` 和在瀏覽器中 javascript 中的 `this` 是不一樣的。 1、**全局中的 `this` 默認是一個空對象**。并且在全局中 `this` 與 `global` 對象沒有任何的關系: ``` console.log(this); {} this.num = 10; console.log(this.num); // 10 console.log(global.num); // undefined ``` 2、在函數中的 `this` ``` function fn(){ this.num = 10; } fn(); console.log(this); // {} console.log(this.num); // undefined console.log(global.num); // 10 ``` 在函數中 `this` 指向的是 `global` 對象,和全局中的 `this` 不是同一個對象,簡單來說,你在函數中通過 `this` 定義的變量就是相當于給 `global` 添加了一個屬性,此時與全局中的 `this` 已經沒有關系了。 如果不相信,看下面這段代碼可以證明。 ``` function fn(){ function fn2(){ this.age = 18; } fn2(); console.log(this); // global console.log(this.age); // 18 console.log(global.age); // 18 } fn(); ``` 3、構造函數中的 `this` ``` function Fn(){ this.num = 998; } var fn = new Fn(); console.log(fn.num); // 998 console.log(global.num); // undefined ``` 在構造函數中 `this` 指向的是它的實例,而不是 `global` 。 4、全局中的 `this` 指向的是 `module.exports`。 ``` this.num = 10; console.log(module.exports); {num:10} console.log(module.exports.num); ``` # nodejs中require的路徑是一個文件夾時發生了什么 ## 參考 [nodejs的require模塊及路徑](http://www.cnblogs.com/pigtail/archive/2013/01/14/2859929.html) http://blog.csdn.net/theanarkh/article/details/54783375 # `require`和`import`的區別 ES6標準發布后,module成為標準,標準的使用是以export指令導出接口,以import引入模塊,但是在我們一貫的node模塊中,我們采用的是CommonJS規范,使用require引入模塊,使用module.exports導出接口。 不把require和import整清楚,會在未來的標準編程中死的很難看。 請記住,現在還沒有JavaScript引擎,可以原生支持ES6模塊,在不久的未來應該可以支持。你說自己在使用Babel。默認情況下,`Babel` 轉化`import` 和 `export` 聲明為 CommonJS (`require/module.exports`) 。因此,即使您使用了ES6模塊語法,如果您在Node中運行代碼,其實您將會使用轉化后的CommonJS。 CommonJS允許您動態加載`require`模塊。甚至不需要賦值給某個變量之后再使用,比如: ```js require('./a')(); // a模塊是一個函數,立即執行a模塊函數 var data = require('./a').data; // a模塊導出的是一個對象 var a = require('./a')[0]; // a模塊導出的是一個數組 ``` 你在使用時,完全可以忽略模塊化這個概念來使用require,僅僅把它當做一個node內置的全局函數,它的參數甚至可以是表達式: ```js require(process.cwd() + '/a'); ``` 但是ES6`import`的則不同,它必須放在文件開頭。它不會將整個模塊運行后賦值給某個變量,而是只選擇import的接口進行編譯,這樣在性能上比require好很多。 `import` 具有聲明提升效果,會首先執行。所以最好不要混用`import`和`require`。 import 是 ES6 標準,如果可能,首先使用 import, 如果不行,就用`require`。 因為ES6 模塊是標準,所以現在還是推薦使用`import`,避免未來不必要的更改。 ### 參考 [編寫瀏覽器和Node.js通用的JavaScript模塊](http://harttle.com/2016/10/12/js-modules-for-browser-and-node.html) [不要混用 import 和 require](https://robin-front.github.io/2017/07/10/dont-mixin-import-and-require/) # `exports` 和 `module.exports` 的區別 node系統會自動給 執行文件增加2個變量 `exports` 和 `module`, 同時,`module`對象會創建一個叫`exports`的屬性。 兩者唯一的關系:默認他們初始都指向同一個空對象`{}`: 于是就有了 ``` exports => {} <=module.exports. ``` 如果其中一個**不指向這個空對象了, 那么他們的關系就沒有了**。 其實大家用內存塊的概念去理解,就會很清楚了。 然后呢,為了避免糊涂,盡量都用 `module.exports` 導出,然后用 `require` 導入。 ## 示例 那么,這樣寫是沒問題的: ``` exports.name = function(x){ console.log(x); }; //和下面這個一毛一樣,因為都是修改的同一內存地址里的東西 module.exports.name = function(x){ console.log(x); }; ``` 但是這樣寫就有了區別了: ``` exports = function(x){ console.log(x); }; // 上面的 function 是一塊新的內存地址,導致exports與module.exports不存在任何關系,而require方能看到的只有 module.exports 這個對象,看不到exports對象,所以這樣寫是導不出去的。 //下 面的寫法是可以導出去的。說句題外話,module.exports 除了導出對象,函數,還可以導出所有的類型,比如字符串、數值等。 module.exports = function(x){ console.log(x); }; ``` 如果 `module.exports` 已經被改變了,那么 `exports` 上的所有屬性都會被忽略。 ## 總結 用白話講就是,`exports` 只輔助 `module.exports` 操作內存中的數據,辛辛苦苦各種操作數據完,累得要死,結果到**最后真正被 `require` 出去的內容還是 `module.exports` 的**,真是好苦逼啊。 如果你只是添加方法或屬性,只要操作`exports`就可以了。 除非您打算將模塊的對象類型從傳統的 ‘module instance’ 更改為其他對象類型,否則 `exports` 是官方推薦的(如果你的模塊是一個典型的node模塊實例,那么使用 `exports`。)。 ## 參考 > [export 和 module.export 的區別](https://www.jianshu.com/p/e452203d56c4) > [Node.js 模塊里 exports 與 module.exports 的區別?](https://www.zhihu.com/question/26621212) [Node.js Module – exports vs module.exports](http://www.hacksparrow.com/node-js-exports-vs-module-exports.html) > https://nodejs.org/api/modules.html#modules_module_exports ## 為什么會加上`.default` **在文件中使用 CommonJS 模塊導入方式 require 引入 ESM,則需要使用`.default`來獲取實際的組件選項** 其中是因為 bable 轉換的變化: babel@5 及之前的版本可以把`export`和`import`轉成 node 的`module.exports`和`require` , babel@6 版本開始不再把`export default`轉成 node 的`module.exports`,參考[https://github.com/babel/babel/issues/2212](https://github.com/babel/babel/issues/2212)。 如使用Babel@6 編譯下面的模塊: ~~~ export default 'router' ~~~ 可得到以下編譯結果,你也可以打開[babeljs.io](https://babeljs.io/repl)在線編譯試試看: ~~~ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = 'router'; ~~~ 因此,需要`require`形式引入模塊,需要添加`.default`: ~~~ require('./router.js') // {默認值:'router'} require('./router.js').default // 'router' ~~~ ## 解決 通過引入 [babel-plugin-add-module-exports](https://github.com/59naga/babel-plugin-add-module-exports) 這個plugin 可以解決這個問題,以下是編譯效果: ~~~ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = 'router'; module.exports = exports['default']; ~~~ > [require一個node模塊加上.default](https://www.cnblogs.com/PeunZhang/p/12736940.html) # glob 模式匹配 使用 extglob 的 [glob模式匹配](https://en.wikipedia.org/wiki/Glob_%28programming%29) 表示法,類似于 Git 處理 [`gitignore`](http://git-scm.com/docs/gitignore) 的規則和 [Bower](https://github.com/bower/bower) 處理 `ignore` 規則。 [此Wiki頁面](http://mywiki.wooledge.org/glob) 是更詳細的參考,以下是使用的示例的說明: * `**` — 匹配任意子目錄中的任何文件或文件夾 * `**/.*` — 匹配任意子目錄中以'`.`'開頭的任何文件(通常是隱藏文件,例如`.git`文件夾中的文件) * `**/*.@(jpg|jpeg|gif|png)` — 匹配任意子目錄中以以下任意一個結尾的任何文件:`.jpg`,`.jpeg`,`.gif`, 或者`.png` > [firebase-full-config](https://firebase.google.com/docs/hosting/full-config#glob_pattern_matching)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看