<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、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                >[success] # CommonJS 在node服務器端出現 1. **CommonJS是一個規范**,最初提出來是在瀏覽器以外的地方使用(創建一個專注于非瀏覽器(即服務器端、命令行、桌面)功能的通用 JavaScript 庫。),并且當時被命名為**ServerJS**,后來為了體現它的廣泛性,修改為**CommonJS**,**簡稱為CJS**,這個規范約定了 1.1. **一個文件就是一個模塊** 1.2. **每個模塊都有單獨的作用域** 1.3. 通過 **modeule.exports也可以exports** 導出成員 1.4. 通過 **require 函數**載入模塊 2. Node中對**CommonJS規范進行了支持和實現** 2.1. 在Node中每**一個js文件都是一個單獨的模塊** 2.2. **這個模塊中包括CommonJS規范的核心變量**:exports、module.exports、require >[info] ## node 模塊化 ~~~ 1.在客戶客戶端可以通過'sprict' 標簽對各個模塊進行引入,上一章節演示了演變過程,為了達到屬性私有,命名 不重復等問題,利用立即執行函數并且將要暴露的變量掛在到'windows'。 2.'node' 服務端運行環境沒有'sprict'引入形式,單純對其進行掛在全局變量的處理,看起來也不是一個明智的做法, 像案例一這樣就不是好的解決方式 3.在瀏覽器中,頂層的作用域是全局作用域。 這意味著在瀏覽器中,`var something`將定義新的 全局變量。 在 Node.js 中這是不同的。 頂層作用域不是全局作用域;Node.js 模塊內的 `var something`將是該模塊本地的,簡單的說也就是你在node 環境中定義了一下代碼 var a = 1 此時通過'global.a' 也是無法訪問到的 ~~~ >[danger] ##### 案例一 ~~~ 1.創建一個結構目錄如下: src ├── index.js └── example.js 2.這種形式和上個章節講到的模塊演變過程中在瀏覽器大家通過window 將要暴露出去的變量進行 掛在是一個思路。利用node 的頂層作用域中的global 作為'中介',同樣的弊端也一樣同名會被 修改 ~~~ * example.js ~~~ 1.node 每個文件就是一個模塊,有自己的作用域。在一個文件里面定義的變量、函數、類,都是私有的, 對其他文件不可見。因此下面的 x 和 addX 都是可以理解成私有的外界不能訪問 2.將'g' 屬性掛在到'global' 全局屬性上,此時其他文件可以訪問,相對的導致其他文件如果有相同的通過'global' 到處的'g' 屬性會被覆蓋 ~~~ ~~~ var x = 5; var addX = function (value) { return value + x; }; global.g = 11 ~~~ * index.js ~~~ require('./example.js') // 正常打印出11 console.log(global.g); // addX 和 x 屬性為私有的 下面運行報錯沒有該屬性 console.log(x) console.log(addX ) ~~~ >[success] # module 和 require 1. CommonJS規范規定,每個模塊內部,**module變量代表當前模塊。這個變量是一個對象,它的exports屬性(即module.exports)是對外的接口**。加載某個模塊,其實是加載該模塊的**module.exports**屬性。 2. require方法用于加載模塊。 3. 這種設計和上個章節中模塊化演變歷程中通過對象導出模塊思路很像,首先假設我們在瀏覽器環境需要模擬一個簡單node這類思路,要滿足幾個簡單的條件 3.1. 每個文件定義的var 變量不能在通過window 訪問 3.2. 需要可以訪問被暴露的對象 ~~~ // 一個最簡單的思路應用 (function () { var a = 1 window.module.export = { name: 18, } })() ~~~ 但實際上node 模塊化比這個要復雜的多 >[danger] ##### node cjs 使用案例 1. node **每一個文件就是一個模塊**,**因此文件和文件直接是不能訪問**,一個文件叫做**一個模塊**,每個模塊有屬于模塊自己的全局變量(**是模塊級別的**不是全局的),`__dirname、__filename、exports、module、require()` 2. 其中`exports `和 `module.exports` 都是導出,`require `是導入,**module對象的exports屬性是exports對象的一個引用 `exports = module.exports `**,require 導出也是`module.exports`,正因為exports 指向了 module.exports因此我們怎加exports對象屬性即`exports .a = 1` 也是可以通過require 導出,但是如果切斷了`exports ={ a:1 }`此時**module.exports** 還是為空因此`require`導出也是空 * aa.js ~~~ const a = 1 // 導出a // exports.a = a // 這樣不可以,切斷了exports 和module.exports關聯 // exports = {} // 想導出一個對象 module.exports = { a, } ~~~ * bb.js ~~~ // 導出aa 文件模塊 const moduleA = require('./aa') console.log(moduleA.a) // 1 ~~~ 3. CommonJS模塊是對象,是'**運行時加載**',運行時才把模塊掛載在exports之上(加載整個模塊的所有)模塊輸出的是'**一個值的拷貝**' (下面案例演示了證明了是一個copy過程) * 創建aa.js 文件用來導出,此時aa 文件值想要被別的文件使用打破自己模塊的壁壘使用`exports ` ~~~ const a = 1 setTimeout(() => { exports.a = 12 // 一秒鐘后改變值 }, 1000) setTimeout(() => { console.log(exports.a) // 1.5秒后 接收 bb 哪里更改值 打印12 }, 1500) // 導出a exports.a = a ~~~ * bb 用來接受aa 模塊傳來的可以訪問的值 ~~~ // 導出aa 文件模塊 const moduleA = require('./aa') console.log(moduleA.a) // 1 setTimeout(() => { console.log(moduleA.a) // 12 }, 1000) ~~~ >[info] ## 了解module ~~~ 1.`module.id`模塊的識別符,通常是帶有絕對路徑的模塊文件名。 2.`module.filename`模塊的文件名,帶有絕對路徑。 3.`module.loaded`返回一個布爾值,表示模塊是否已經完成加載。 4.`module.parent`返回一個對象,表示調用該模塊的模塊。 5.`module.children`返回一個數組,表示該模塊要用到的其他模塊。 6.`module.exports`表示模塊對外輸出的值。 7.這些對象在所有模塊中都可用。 以下變量可能看起來是全局的,但實際上不是。 它們只存在于 模塊的作用域中,簡單的說這些變量也不是直接掛在到global 上也是屬于每個模塊獨立的,并 不是全局統一共享的: __dirname __filename exports module require() 8.在執行模塊代碼之前,Node.js 將使用如下所示的函數封裝器對其進行封裝通過這樣做Node.js 實現了以下幾點: 8.1.它將頂層變量(用 var、const 或 let 定義)保持在模塊而不是全局對象的范圍內。 8.2.它有助于提供一些實際特定于模塊的全局變量,例如: module 和 exports 對象,實現者可以用來從模塊中導出值。 便利變量 __filename 和 __dirname,包含模塊的絕對文件名和目錄路徑 // 在重新來看模型 (function(exports, require, module, __filename, __dirname) { // 模塊代碼實際存在于此處 }); ~~~ >[danger] ##### module ~~~ 1.在node 文件中 寫入'console.log(module)' 執行打印,下面的打印每個人環境對應的地址是不同,以我的電腦 打印輸出如下 Module { id: '.', path: '/mnt/d/js-study/easyTest/src', exports: {}, parent: null, filename: '/mnt/d/js-study/easyTest/src/index.js', loaded: false, children: [], paths: [ '/mnt/d/js-study/easyTest/src/node_modules', '/mnt/d/js-study/easyTest/node_modules', '/mnt/d/js-study/node_modules', '/mnt/d/node_modules', '/mnt/node_modules', '/node_modules' ] } ~~~ >[danger] ##### 關于exports 變量 ~~~ 1.在將文件變量導出的時候經常有下面兩種寫法 module.exports = { name: 'w' } exports.name = "w" 2.'module.exports'屬性表示當前模塊對外輸出的接口,其他文件加載該模塊,實際上就是讀取 'module.exports'變量,可以理解成對外暴露的變量,即像以前模塊化的形式掛在到'windows'變量類似 可以理解成掛在到'module.exports' 3.Node為每個模塊提供一個exports變量,指向module.exports,但是不能直接將exports變量指向一個值, 因為這樣等于切斷了exports與module.exports的聯系,舉個例子 exports = module.exports // 切斷了聯系 exports = { name: 'w' } ~~~ * 創建案例 ~~~ module.exports = { name: 'w' } console.log(module); ~~~ * 打印結果 ~~~ Module { id: '.', path: '/mnt/d/js-study/easyTest/src', exports: { name: 'w' }, parent: null, filename: '/mnt/d/js-study/easyTest/src/example.js', loaded: false, children: [], paths: [ '/mnt/d/js-study/easyTest/src/node_modules', '/mnt/d/js-study/easyTest/node_modules', '/mnt/d/js-study/node_modules', '/mnt/d/node_modules', '/mnt/node_modules', '/node_modules' ] } ~~~ >[danger] ##### require 1. **require命令**的基本功能是,讀入并執行一個JavaScript文件,然后返回該模塊的**exports對象**。**如果沒有發現指定模塊,會報錯**。 1.1. 如果require(x),**x導入是核心模塊**(path、http)會直接返回核心模塊,并且停止查找 1.2. 如果require(x),**X是以 ./ 或 ../ 或 /(根目錄)開頭的**,**如果有后綴名**,按照后綴名的格式查找對應的文件,**如果沒有后綴名**,會按照如下順序,**直接查找文件X-》查找X.js文件-》查找X.json文件 -》查找X.node文件**, 沒有找到文件就當作文件夾處理會依次找文件夾下的 **X/index.js文件=》X/index.json文件=》X/index.node文件**,都沒找到就報錯 1.3. **直接是一個X(沒有路徑),并且X不是一個核心模塊** 就會去**node_modules** 中找 2. 通過下面例子可以看出'**require**' 命令將模塊的'**module.exports**' 進行導出使用 * 舉個例子 ~~~ var example = require('./example.js'); example // { // message: "hi", // say: [Function] // } // 如果模塊輸出的是一個函數 而不是一個對象 module.exports = function () { console.log("hello world") } require('./example2.js')() ~~~ * 案例二打印導入的module ~~~ // 忽略兩個導入文件中的具體內容 require('./firstModules.js') require('./second.js') console.log(module) ~~~ ~~~ 1.可以看到當前文件的module 變量中children 明確記錄了require 導入一些具體詳情 <ref *1> Module { id: '.', path: 'd:\\test-js\\testjs\\src', exports: {}, parent: null, filename: 'd:\\test-js\\testjs\\src\\index.js', loaded: false, children: [ Module { id: 'd:\\test-js\\testjs\\src\\firstModules.js', path: 'd:\\test-js\\testjs\\src', exports: [Object], parent: [Circular *1], filename: 'd:\\test-js\\testjs\\src\\firstModules.js', loaded: true, children: [], paths: [Array] }, Module { id: 'd:\\test-js\\testjs\\src\\second.js', path: 'd:\\test-js\\testjs\\src', exports: [Object], parent: [Circular *1], filename: 'd:\\test-js\\testjs\\src\\second.js', loaded: true, children: [], paths: [Array] } ], paths: [ 'd:\\test-js\\testjs\\src\\node_modules', 'd:\\test-js\\testjs\\node_modules', 'd:\\test-js\\node_modules', 'd:\\node_modules' ] } ~~~ >[info] ## cjs 模塊加載過程 1. 模塊在被第一次引入時,模塊中的js代碼會被運行一次 2. 模塊被多次引入時,會緩存,**最終只加載(運行)一次**,**每個模塊對象module都有一個屬性:loaded,為false表示還沒有加載,為true表示已經加載** * 了解webpack 可能發現,webpack 打包后也是cjs,那不是和結論沖突了,webpack打包后例如你代碼開發階段是分成了100個模塊但是打包后webpack **all in one** 特性最后除非是特別設置 那整體打包后往往只有一個文件,在一個文件內讀取在一個文件做了模塊導入導出 ![](https://img.kancloud.cn/c8/96/c896a7f167ba355cf3fe24b2d0dd3cd0_878x760.png) 3. 關于循環加載 ??? 后續查 >[info] ## cjs 總結 1. CommonJS**加載模塊是同步的**,只有等到對應的模塊加載完畢,當前模塊中的內容才能被運行,**在服務器加載的js文件都是本地文件**,但相比**在瀏覽器**加載js文件需要先從服務器將**文件下載下來**,**之后再加載運行**,采用同步的就意味著后續的js代碼都無法正常運行,即使是一些簡單的DOM操作 >[info] ## 實際原理和構想 [「萬字進階」深入淺出 Commonjs 和 Es Module ](https://juejin.cn/post/6994224541312483336) [讀懂CommonJS的模塊加載 ](https://juejin.cn/post/6844903685466619911#heading-3) >[info] ## 如何在瀏覽器運行cjs [# 瀏覽器加載 CommonJS 模塊的原理與實現](https://www.ruanyifeng.com/blog/2015/05/commonjs-in-browser.html) >[info] ## 參考地址 [# CommonJS規范](https://javascript.ruanyifeng.com/nodejs/module.html#)
                  <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>

                              哎呀哎呀视频在线观看