国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > JavaScript > 正文

Javarscript中模塊(module)、加載(load)與捆綁(bundle)詳解

2019-11-19 16:28:04
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

JS模塊簡(jiǎn)介

js模塊化,簡(jiǎn)單說(shuō)就是將系統(tǒng)或者功能分隔成單獨(dú)的、互不影響的代碼片段,經(jīng)過(guò)嚴(yán)格定義接口,使各模塊間互不影響,且可以為其他所用。

常見(jiàn)的模塊化有,C中的include (.h)文件、java中的import等。

為什么JS需要模塊

很顯然,沒(méi)有模塊我們也可以實(shí)現(xiàn)同樣的功能,為什么我們還要使用模塊來(lái)寫(xiě)js代碼呢?下面幾點(diǎn)是模塊化給我們帶來(lái)的一些變化:

  • 抽象代碼:我們?cè)谑褂媚K來(lái)調(diào)用一個(gè)api時(shí),可以不用知道內(nèi)部是如何實(shí)現(xiàn)的,避免去理解其中復(fù)雜的代碼;
  • 封裝代碼:在不需要再次修改代碼的前提下,我們可以在模塊內(nèi)部隱藏其具體實(shí)現(xiàn);
  • 復(fù)用代碼:一些常用的、通用的功能,以模塊來(lái)實(shí)現(xiàn)可以避免過(guò)多的重復(fù)代碼;
  • 管理依賴(lài):可以通過(guò)簡(jiǎn)單的修改依賴(lài)項(xiàng)來(lái)管理功能的實(shí)現(xiàn),而不需要去重新修改自己內(nèi)部的代碼實(shí)現(xiàn)。

ES5及之前的模塊系統(tǒng)

在ES5及之前版本,還沒(méi)有原生的模塊語(yǔ)法。不過(guò)這并不代表ES5之前,前端沒(méi)有使用模塊。簡(jiǎn)單介紹兩種:IIFE、Revealing Module.

IIFE

Immediately Invoked Function Expression,立即執(zhí)行函數(shù)表達(dá)式。

(function(){  // ... })()

看上面的代碼,IIFE可以說(shuō)成是一個(gè)在定義的時(shí)候就執(zhí)行的匿名函數(shù)。注意函數(shù)是先被”()”包起來(lái)了,然后后面緊跟”()”表示執(zhí)行函數(shù)。如果是以下代碼,將會(huì)報(bào)錯(cuò):

function(){  console.log('test'); }() // => Uncaught SyntaxError: Unexpected token )

這種寫(xiě)法表示,先定義一個(gè)匿名函數(shù),然后再去解析”()”。由于在第一行”function”出現(xiàn)在首位,這表明此處定義一個(gè)函數(shù),函數(shù)后緊跟”()”,此時(shí)表示單獨(dú)解析”()”,就會(huì)報(bào)出上面的錯(cuò)誤信息,因此需要先將函數(shù)定義包裹起來(lái)。
“(function…)”這種寫(xiě)法表示執(zhí)行”()”內(nèi)部代碼,并返回該語(yǔ)句執(zhí)行結(jié)果,此處返回結(jié)果為該函數(shù),后面緊跟”()”即表示執(zhí)行該函數(shù)。IIFE可以幫助我們做到:

  • 不需要了解具體的代碼實(shí)現(xiàn)情況下取得想要的效果;
  • 在內(nèi)部定義的變量不會(huì)污染全局作用域。

顯而易見(jiàn),這種編碼方式并沒(méi)有提供良好的機(jī)制來(lái)解決依賴(lài)管理問(wèn)題。

Revealing Module

根據(jù)字面暫解釋為揭示模式,與IIFE形式類(lèi)似,但是提供了一個(gè)返回值。方便集中管理公有的api,使模塊、公用api更加簡(jiǎn)潔清晰。

// Expose module as global variable var singleton = function(){  // Inner logic  function sayHello(){  console.log('Hello');  }  // Expose API  return {  sayHello: sayHello  } }()

稍微注意下,上面的代碼,我們并沒(méi)有用”()”去包裹,因?yàn)殛P(guān)鍵字”function”并不在該行的開(kāi)頭。

我們可以像下面這樣使用模塊api:

// Access module functionality singleton.sayHello(); // => Hello

當(dāng)然,我們也可以以構(gòu)造函數(shù)形式導(dǎo)出:

// Expose module as global variable var Module = function(){  // Inner logic  function sayHello(){  console.log('Hello');  }  // Expose API  return {  sayHello: sayHello  } }

請(qǐng)注意,上面函數(shù)在定義的時(shí)候并沒(méi)有執(zhí)行。

我們可以這么使用它:

var module = new Module();module.sayHello(); // => Hello

與IIFE一樣,揭示模式并沒(méi)有提供良好的解決依賴(lài)管理的方案。

更多模塊化解決方案

ES6或者ES2015,自帶原生的模塊語(yǔ)法。

在這之前,有以下幾種常見(jiàn)的用于模塊化的解決方案:

  • AMD
  • CMD
  • CommonJs
  • UMD
  • System.register
  • ES6

AMD

AMD,Asynchronous Module Definition,異步模塊定義。AMD形式被用于瀏覽器端,使用”define”來(lái)定義模塊依賴(lài):

//Calling define with a dependency array and a factory function define(['dep1', 'dep2'], function (dep1, dep2) {  //Define the module value by returning a value.  return function () {}; });

CMD

CMD,Common Module Definition,通用模塊定義。該規(guī)范由國(guó)內(nèi)大神玉伯提出,與AMD區(qū)別在與AMD是依賴(lài)關(guān)系前置,有該依賴(lài)就必須先加載依賴(lài),CMD是按需加載。

// CMD define(function(require, exports, module) { var a = require('./a') a.doSomething() // 此處略去 100 行 var b = require('./b') // 依賴(lài)可以就近書(shū)寫(xiě) b.doSomething() // ... }) // AMD 默認(rèn)推薦的是 define(['./a', './b'], function(a, b) { // 依賴(lài)必須一開(kāi)始就寫(xiě)好 a.doSomething() // 此處略去 100 行 b.doSomething() ... })

CommonJs

CommonJs在Node.js中用的較多,使用”require”來(lái)定義依賴(lài),使用”module.exports”來(lái)定義模塊:

var dep1 = require('./dep1'); var dep2 = require('./dep2'); module.exports = function(){  // ... }

UMD

UMD,Universal Module Definition,通用模塊定義。可以用于瀏覽器端與Node.js端:

(function (root, factory) {  if (typeof define === 'function' && define.amd) {  // AMD. Register as an anonymous module.   define(['b'], factory);  } else if (typeof module === 'object' && module.exports) {  // Node. Does not work with strict CommonJS, but  // only CommonJS-like environments that support module.exports,  // like Node.  module.exports = factory(require('b'));  } else {  // Browser globals (root is window)  root.returnExports = factory(root.b);  } }(this, function (b) {  //use b in some fashion.  // Just return a value to define the module export.  // This example returns an object, but the module  // can return a function as the exported value.  return {}; }));

System.register

System.register方式設(shè)計(jì)初衷主要是為了在ES5中能夠支持ES6模塊語(yǔ)法:

import { p as q } from './dep'; var s = 'local'; export function func() {  return q; } export class C { }

ES6 module

ES6中自帶原生的模塊語(yǔ)法,使用關(guān)鍵字”export”來(lái)導(dǎo)出模塊的公用api:

// lib.js // Export the function export function sayHello(){  console.log('Hello'); } // Do not export the function function somePrivateFunction(){  // ... }

以關(guān)鍵字”import”來(lái)導(dǎo)入模塊:

import { sayHello } from './lib'; sayHello(); // => Hello

目前各瀏覽器對(duì)ES6的支持度不一,因此我們現(xiàn)在需要使用編譯器,像Babel,來(lái)將ES6的代碼編譯成ES5的形式。

模塊加載器

一個(gè)模塊加載器可以理解模塊,并以固定的形式來(lái)加載模塊。

模塊加載器工作在運(yùn)行時(shí),流程大致如下:

  • 你在瀏覽器中運(yùn)行模塊加載器;
  • 你告訴模塊加載器需要加載哪個(gè)主文件;
  • 模塊加載器下載并解析主文件;
  • 模塊加載器按需加載其他文件。

一些比較常見(jiàn)的模塊加載器有:

  • RequireJS:以AMD風(fēng)格加載模塊;
  • SeaJS:以CMD風(fēng)格加載模塊;
  • SystemJS:以AMD, CommonJS, UMD 或者 System.register風(fēng)格加載模塊;
  • jspm:jspm基于SystemJS,是模塊加載器,同時(shí)也具備瀏覽器端包管理功能。

模塊打包

模塊打包可以替換模塊加載器。

然而,相比模塊加載器,模塊打包動(dòng)作是在編譯時(shí)運(yùn)行的:

  • 使用模塊打包在編譯期生成一個(gè)js文件;(例如bundle.js)
  • 在瀏覽器中加載該文件。

截止目前,比較常用的模塊打包方案有以下兩種:

  • Browserify:為CommonJS模塊打包;
  • Webpack: 為AMD、CommonJS、ES6模塊打包。

總結(jié)

為了在現(xiàn)代js開(kāi)發(fā)環(huán)境中更好的使用這些工具,你首先需要知道模塊、模塊化解決方案、模塊加載、模塊打包之前的區(qū)別。

模塊是一段封裝好的代碼,可以以公用api形式導(dǎo)出并在其他代碼中被加載和調(diào)用;

模塊化解決方案或者模塊化思想,實(shí)際含義是定義一個(gè)模塊的語(yǔ)法。由于定義語(yǔ)法的差異,目前常用的有AMD、CMD、CommonJS、UMD等;

模塊加載,在運(yùn)行期解析和加載模塊。常見(jiàn)的有RequireJS、SeaJS、SystemJS和jspm;

模塊打包,其替換了模塊加載的概念,在編譯期間生成一個(gè)所有代碼整合后的bundle.js文件。常見(jiàn)的有Browserify和Webpack。

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家武林網(wǎng)的支持。

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 额尔古纳市| 共和县| 新田县| 台中市| 抚远县| 射阳县| 临城县| 江源县| 深泽县| 萨迦县| 始兴县| 时尚| 马山县| 宁城县| 万源市| 分宜县| 米易县| 盐山县| 安康市| 大埔区| 沙田区| 鄄城县| 芦溪县| 平阴县| 泸州市| 阿鲁科尔沁旗| 基隆市| 万源市| 嘉荫县| 三江| 镇雄县| 孟州市| 黄大仙区| 衢州市| 和田县| 大安市| 都兰县| 河东区| 裕民县| 拉孜县| 大冶市|