<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一次搞懂-JavaScript 模塊化詳解

          共 7540字,需瀏覽 16分鐘

           ·

          2021-05-21 01:40

          作者:九旬

          來源:SegmentFault 思否社區(qū)

          模塊化的意義

          將代碼拆分成獨(dú)立的塊,然后再把這些塊使用模塊模式連接起來實(shí)現(xiàn)不同的功能。

          就像小時(shí)候玩的拼圖一樣,不同的拼圖組合在一起就可以拼成任意的形狀。

          這種模式的背后思想也很簡單:把邏輯分塊、各自封裝,相互獨(dú)立,同時(shí)自行決定引入執(zhí)行那些外部模塊以及暴露自身的那些模塊。

          這個(gè)基本的思想是所有的 JavaScript 模塊系統(tǒng)的基礎(chǔ)。

          文中代碼案例地址:

          https://github.com/AnsonZnl/JS-Modules-Sample

          模塊化的好處

          • 避免命名沖突(減少命名空間污染)
          • 更好的分離, 按需加載
          • 更高復(fù)用性
          • 高可維護(hù)性

          JS 中常見的模塊

          IIFE 模式:匿名函數(shù)自調(diào)用(閉包)

          主要應(yīng)用在瀏覽器端。
          利用閉包的原理創(chuàng)造一個(gè)獨(dú)有的函數(shù)作用域來保存私有變量,達(dá)到模塊化的效果。
          使用
          HTML
          <script type="text/javascript" src="module.js"></script>
          <script type="text/javascript">
            console.log(myModule.get()); // output-data(獲取內(nèi)部數(shù)據(jù))
            myModule.set("new data"); // 設(shè)置內(nèi)部數(shù)據(jù)
            console.log(myModule.data); //output-undefined (不能訪問模塊內(nèi)部數(shù)據(jù))
            myModule.data = "xxxx"; //不是修改的模塊內(nèi)部的data
            console.log(myModule.get()); //output-new data 修改后的值
          </script>
          JS
          // module.js文件
          (function(window) {
            let data = "data";
            //獲取數(shù)據(jù)
            function get() {
              return data;
            }
            // 修改數(shù)據(jù)
            function set(val) {
              data = val;
            }
            //暴露行為
            window.myModule = {
              get,
              set,
            };
          })(window);

          CommonJS

          主要應(yīng)用在服務(wù)端,如果在瀏覽器端運(yùn)行需要借助其他工具(Browserify)。
          暴露模塊: module.exports = value或者exports.xx = value(exports 是一個(gè)導(dǎo)出的對象)
          引入模塊: require(xx),如果是第三方模塊,xxx 為模塊名,如果為自定義模塊,xxx 為模塊的文件路徑。
          特點(diǎn)
          • 所有代碼都運(yùn)行在模塊作用域,不會(huì)污染全局作用域。
          • 模塊可以多次加載,但是只會(huì)在第一次加載時(shí)運(yùn)行一次,然后運(yùn)行結(jié)果就被緩存了,以后再加載,就直接讀取緩存結(jié)果。要想讓模塊再次運(yùn)行,必須清除緩存。
          • 模塊加載的順序,按照其在代碼中出現(xiàn)的順序。
          使用
          在 Node 中 安裝 uniq 函數(shù)。
          npm init
          npm install uniq --save
          // module.js
          let arr = [1, 2, 2, 3, 3];
          module.exports = {
            arr,
          };
          // app.js
          let module1 = require("./module.js");
          let uniq = require("uniq");

          console.log(uniq(module1.arr)); // [1,2,3]

          AMD

          全稱是 Asynchronous Module Definition - 異步模塊定義
          和 CommonJS 不同的是 AMD 采用非同步的方式來加載模塊。
          基本語法
          定義暴露模塊
          // 定義沒有依賴的模塊
          define(function() {
            return 模塊;
          });
          // 定義有依賴的模塊
          define(["module1""module2"], function(m1, m2) {
            return 模塊;
          });
          引入使用模塊
          require(["module1""module2"], function(m1, m2) {
            使用m1 和 m2;
          });
          使用案例
          <!-- index.html -->
          <body>
            <!-- 引入require.js并指定js主文件的入口 -->
            <script
              data-main="main"
              src="https://cdn.bootcdn.net/ajax/libs/require.js/2.3.6/require.js"
            ></script>
          </body>
          // main.js
          (function() {
            require(["module.js"], function(module) {
              let currentUrl = module.getUrl();
              alert("當(dāng)前頁面的URl:" + currentUrl);
            });
          })();
          // module.js
          // 定義模塊
          define(function() {
            let url = window.location.href;

            function getUrl() {
              return url.toUpperCase();
            }
            // 暴露模塊
            return {
              getUrl,
            };
          });
          更多的使用方法請參考:https://requirejs.org/

          CMD

          CMD---是 SeaJS 在推廣過程中對模塊定義的規(guī)范化產(chǎn)出,是一個(gè)同步模塊定義,是 SeaJS 的一個(gè)標(biāo)準(zhǔn),SeaJS 是 CMD 概念的一個(gè)實(shí)現(xiàn),SeaJS 是淘寶團(tuán)隊(duì)提供的一個(gè)模塊開發(fā)的 JS 框架。
          什么時(shí)候用到什么時(shí)候引入,即用即返回,這是一個(gè)同步概念。
          特點(diǎn): CMD 是 AMD 在基礎(chǔ)上改進(jìn)的一種規(guī)范,和 AMD 不同在于依賴模塊的執(zhí)行機(jī)制不同,CMD 是就近依賴,而 AMD 是前置依賴。
          環(huán)境: 瀏覽器環(huán)境
          語法:
          • 導(dǎo)入:define(function(require, exports, module){})
          • 導(dǎo)出:define(function(){return '值'})
          使用
          // main.js
          define(function(require, exports, module) {
            var moduleA = require("./module.js");
            alert(moduleA.a); // 打印出:hello world
          });
          // module.js
          define(function(require, exports, module) {
            exports.a = "hello world";
          });
          <body>
            <script
              data-main="main"
              src="https://cdn.bootcdn.net/ajax/libs/require.js/2.3.6/require.js"
            ></script>
          </body>

          UMD

          全稱 Universal Module Definition 看名字就知道,特點(diǎn)是兼容 AMD 和 CommonJS 規(guī)范,而且兼容全局引入。
          環(huán)境: 服務(wù)器環(huán)境和瀏覽器端
          UMD 實(shí)現(xiàn)原理很簡單:
          • 先判斷是否支持 AMD(define 是否存在),存在則使用 AMD 方式加載模塊;
          • 再判斷是否支持 Node.js 模塊格式(exports 是否存在),存在則使用 Node.js 模塊格式;
          • 前兩個(gè)都不存在,則將模塊公開到全局(window 或 global)
          使用
          (function(root, factory) {
            if (typeof define === "function" && define.amd) {
              //AMD
              define(["jquery"], factory);
            } else if (typeof exports === "object") {
              //Node, CommonJS之類的
              module.exports = factory(require("jquery"));
            } else {
              //瀏覽器全局變量(root 即 window)
              root.returnExports = factory(root.jQuery);
            }
          })(this, function($) {
            //方法
            function myFuncA() {} // 私有方法,因?yàn)闆]有返回
            function myFuncB() {} // 公共方法,因?yàn)榉祷亓?br>
            //暴露公共方法
            return {
              myFuncB,
            };
          });
          大家平時(shí)引入的 jQuery 的 CND 就是 UMD 的,源碼可以查看:
          https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js

          ES6 Module

          在 ES6 之前,模塊化主要是社區(qū)在推動(dòng)進(jìn)行的,從而出現(xiàn)了 CommonJS 和 AMD 兩個(gè),前者用于服務(wù)器后者用于瀏覽器,ES6 模塊的出現(xiàn)將完全替代 CommonJS 和 AMD 規(guī)范,成為瀏覽器和服務(wù)器通用的解決方案。
          ES6 模塊的設(shè)計(jì)思想是盡量的靜態(tài)化,使得編譯時(shí)就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量。CommonJS 和 AMD 模塊,都只能在運(yùn)行時(shí)確定這些東西。比如,CommonJS 模塊就是對象,輸入時(shí)必須查找對象屬性。
          特點(diǎn) :
          • 按需加載(編譯時(shí)加載)
          • import 和 export 命令只能在模塊的頂層,不能在代碼塊之中(如:if 語句中),import()語句可以在代碼塊中實(shí)現(xiàn)異步動(dòng)態(tài)按需動(dòng)態(tài)加載
          環(huán)境: 服務(wù)器環(huán)境和瀏覽器端
          語法:
          • 導(dǎo)入:import {modules1,modules1,} from '模塊路徑'
          • 導(dǎo)出:export或者export default
          • 動(dòng)態(tài)導(dǎo)入:import('模塊路徑').then(..)
            <!-- 揺樹(tree-shaking) -->
          使用
          Node 中 先安裝 Babel:
          npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/node
          npm install --save @babel/polyfill
          # 然后運(yùn)行
          npx babel-node main.js
          // modules/double.js
          let mes = "Hello Modules for double";
          function sum(value) {
            return `${mes} - ${value * 2}`;
          }
          export default {
            mes,
            sum,
          };
          // main.js
          import module from "./modules/double";
          console.log(module.sum(10)); // Hello Modules for double - 20
          瀏覽器中
          區(qū)別
          • 和 CommonJS 的區(qū)別:
            • CommonJS 模塊輸出的是一個(gè)值得拷貝,ES6 模塊輸出的是值的引用
            • CommonJS 模塊是運(yùn)行時(shí)加載,ES6 模塊是編譯時(shí)輸出接口
            • CommonJS 模塊的 require()是同步加載模塊,ES6 模塊的 import 命令是異步加載,有一個(gè)獨(dú)立的模塊依賴的解析階段。
          缺點(diǎn)
          瀏覽器和服務(wù)器目前的支持不是很好,現(xiàn)階段使用需要借助一些工具(
          Babel)。
          • 瀏覽器支持:在新版本的瀏覽器(如 Chrome)中可以使用<script type="module" src="./foo.js"></script>寫法
          • 服務(wù)器支持(Node)有兩種模式,分別是 ES6 模塊和 CommonJS。
            • 從 Node.js v13.2 開始,默認(rèn)支持 ES6 模塊,但是需要采用.mjs為后綴名、或者在package.json中修改type字段為module(推薦)
            • 使用 CommonJS 的話需要以.cjs為后綴,也可以設(shè)置package.json中修改type字段為commonjs(推薦)。
          最好不要兩者混用。更多的使用方法可以參考:https://es6.ruanyifeng.com/#d...

          總結(jié)

          • CommonJS 規(guī)范主要用于服務(wù)端編程,加載模塊是同步的,這并不適合在瀏覽器環(huán)境,因?yàn)橥揭馕吨枞虞d,瀏覽器資源是異步加載的,因此有了 AMD CMD 解決方案。
          • AMD 規(guī)范在瀏覽器環(huán)境中異步加載模塊,而且可以并行加載多個(gè)模塊。不過,AMD 規(guī)范開發(fā)成本高,代碼的閱讀和書寫比較困難,模塊定義方式的語義不順暢。
          • CMD 規(guī)范與 AMD 規(guī)范很相似,都用于瀏覽器編程,依賴就近,延遲執(zhí)行,可以很容易在 Node.js 中運(yùn)行。不過,依賴 SPM 打包,模塊的加載邏輯偏重
          • ES6 在語言標(biāo)準(zhǔn)的層面上,實(shí)現(xiàn)了模塊功能,而且實(shí)現(xiàn)得相當(dāng)簡單,完全可以取代 CommonJS 和 AMD 規(guī)范,成為瀏覽器和服務(wù)器通用的模塊解決方案。


          點(diǎn)擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開更多互動(dòng)和交流,掃描下方”二維碼“或在“公眾號后臺(tái)回復(fù)“ 入群 ”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~

          - END -


          瀏覽 68
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  极品3p肏屄 | 毛片专区| 久久精品国产人伦 | 亚洲天堂一区在线观看 | 99久久久无码国产一区二区三区 |