摘要:依賴全部加載完成后,調用回調函數規范異步加載模塊規范和很相似,簡單,并與和的規范保持了很大的兼容性在規范中,一個模塊就是一個文件。
拋出問題:
在開發中在導入模塊時經常使用require和import;
導出模塊時使用module.exports/exports或者export/export default;
有時候為了引用一個模塊會使用require奇怪的是也可以使用import????它們之間有何區別呢?
追溯根源,來到Js模塊化規范 1、CommonJS規范(同步加載模塊)</>復制代碼
于是有了菜鳥解惑的搜嘍過程。。。。。。
允許模塊通過require方法來同步加載所要依賴的其他模塊,然后通過exports或module.exports來導出需要暴露的接口。
使用方式:
</>復制代碼
// 導入
require("module");
require("../app.js");
// 導出
exports.getStoreInfo = function() {};
module.exports = someValue;
優點:
簡單容易使用
服務器端模塊便于復用
缺點:
同步加載方式不適合在瀏覽器環境中使用,同步意味著阻塞加載,瀏覽器資源是異步加載的
不能非阻塞的并行加載多個模塊
?為什么瀏覽器不能使用同步加載,服務端可以?
因為模塊都放在服務器端,對于服務端來說模塊加載時
而對于瀏覽器端,因為模塊都放在服務器端,加載的時間還取決于網速的快慢等因素,如果需要等很長時間,整個應用就會被阻塞。
因此,瀏覽器端的模塊,不能采用"同步加載"(CommonJs),只能采用"異步加載"(AMD)。
參照CommonJs模塊代表node.js的模塊系統
AMD(異步加載模塊)采用異步方式加載模塊,模塊的加載不影響后面語句的運行。所有依賴模塊的語句,都定義在一個回調函數中,等到加載完成之后,回調函數才執行。
使用實例:
</>復制代碼
// 定義
define("module", ["dep1", "dep2"], function(d1, d2) {...});
// 加載模塊
require(["module", "../app"], function(module, app) {...});
加載模塊require([module], callback);第一個參數[module],是一個數組,里面的成員就是要加載的模塊;第二個參數callback是加載成功之后的回調函。
優點:
適合在瀏覽器環境中異步加載模塊
可以并行加載多個模塊
缺點:
提高了開發成本,代碼的閱讀和書寫比較困難,模塊定義方式的語義不順暢
不符合通用的模塊化思維方式,是一種妥協的實現
實現AMD規范代表require.js
</>復制代碼
RequireJS對模塊的態度是預執行。由于 RequireJS 是執行的 AMD 規范, 因此所有的依賴模塊都是先執行;即RequireJS是預先把依賴的模塊執行,相當于把require提前了
RequireJS執行流程:
require函數檢查依賴的模塊,根據配置文件,獲取js文件的實際路徑
根據js文件實際路徑,在dom中插入script節點,并綁定onload事件來獲取該模塊加載完成的通知。
依賴script全部加載完成后,調用回調函數
CMD規范(異步加載模塊)CMD規范和AMD很相似,簡單,并與CommonJS和Node.js的 Modules 規范保持了很大的兼容性;在CMD規范中,一個模塊就是一個文件。
定義模塊使用全局函數define,其接收 factory 參數,factory 可以是一個函數,也可以是一個對象或字符串;
factory 是一個函數,有三個參數,function(require, exports, module):
require 是一個方法,接受模塊標識作為唯一參數,用來獲取其他模塊提供的接口:require(id)
exports 是一個對象,用來向外提供模塊接口
module 是一個對象,上面存儲了與當前模塊相關聯的一些屬性和方法
實例:
</>復制代碼
define(function(require, exports, module) {
var a = require("./a");
a.doSomething();
// 依賴就近書寫,什么時候用到什么時候引入
var b = require("./b");
b.doSomething();
});
優點:
依賴就近,延遲執行
可以很容易在 Node.js 中運行
缺點:
依賴 SPM 打包,模塊的加載邏輯偏重
實現代表庫sea.js:SeaJS對模塊的態度是懶執行, SeaJS只會在真正需要使用(依賴)模塊時才執行該模塊
AMD 與 CMD 的區別對于依賴的模塊,AMD 是提前執行,CMD 是延遲執行。不過 RequireJS 從2.0開始,也改成了可以延遲執行(根據寫法不同,處理方式不同)。CMD 推崇 as lazy as possible.
AMD推崇依賴前置;CMD推崇依賴就近,只有在用到某個模塊的時候再去require。
</>復制代碼
// AMD
define(["./a", "./b"], function(a, b) { // 依賴必須一開始就寫好
a.doSomething()
// 此處略去 100 行
b.doSomething()
...
});
// CMD
define(function(require, exports, module) {
var a = require("./a")
a.doSomething()
// 此處略去 100 行
var b = require("./b")
// 依賴可以就近書寫
b.doSomething()
// ...
});
UMD
UMD是AMD和CommonJS的糅合
AMD 以瀏覽器第一原則發展異步加載模塊。
CommonJS 模塊以服務器第一原則發展,選擇同步加載,它的模塊無需包裝。
UMD先判斷是否支持Node.js的模塊(exports)是否存在,存在則使用Node.js模塊模式;在判斷是否支持AMD(define是否存在),存在則使用AMD方式加載模塊。
</>復制代碼
(function (window, factory) {
if (typeof exports === "object") {
module.exports = factory();
} else if (typeof define === "function" && define.amd) {
define(factory);
} else {
window.eventUtil = factory();
}
})(this, function () {
//module ...
});
ES6模塊化
ES6 在語言標準的層面上,實現了模塊功能,而且實現得相當簡單,完全可以取代 CommonJS 和 AMD 規范,成為瀏覽器和服務器通用的模塊解決方案。
ES6 模塊設計思想:盡量的靜態化、使得編譯時就能確定模塊的依賴關系,以及輸入和輸出的變量(CommonJS和AMD模塊,都只能在運行時確定這些東西)。
使用方式:
</>復制代碼
// 導入
import "/app";
import React from “react”;
import { Component } from “react”;
// 導出
export function multiply() {...};
export var year = 2018;
export default ...
...
優點:
容易進行靜態分析
面向未來的 EcmaScript 標準
缺點:
原生瀏覽器端還沒有實現該標準
全新的命令字,新版的 Node.js才支持。
回到問題“require與import的區別”require使用與CommonJs規范,import使用于Es6模塊規范;所以兩者的區別實質是兩種規范的區別;
CommonJS:
對于基本數據類型,屬于復制。即會被模塊緩存;同時,在另一個模塊可以對該模塊輸出的變量重新賦值。
對于復雜數據類型,屬于淺拷貝。由于兩個模塊引用的對象指向同一個內存空間,因此對該模塊的值做修改時會影響另一個模塊。
當使用require命令加載某個模塊時,就會運行整個模塊的代碼。
當使用require命令加載同一個模塊時,不會再執行該模塊,而是取到緩存之中的值。也就是說,CommonJS模塊無論加載多少次,都只會在第一次加載時運行一次,以后再加載,就返回第一次運行的結果,除非手動清除系統緩存。
循環加載時,屬于加載時執行。即腳本代碼在require的時候,就會全部執行。一旦出現某個模塊被"循環加載",就只輸出已經執行的部分,還未執行的部分不會輸出。
ES6模塊
ES6模塊中的值屬于【動態只讀引用】。
對于只讀來說,即不允許修改引入變量的值,import的變量是只讀的,不論是基本數據類型還是復雜數據類型。當模塊遇到import命令時,就會生成一個只讀引用。等到腳本真正執行時,再根據這個只讀引用,到被加載的那個模塊里面去取值。
對于動態來說,原始值發生變化,import加載的值也會發生變化。不論是基本數據類型還是復雜數據類型。
循環加載時,ES6模塊是動態引用。只要兩個模塊之間存在某個引用,代碼就能夠執行。
最后:require/exports 是必要通用且必須的;因為事實上,目前你編寫的 import/export 最終都是編譯為 require/exports 來執行的。
參考
AMD與CMD規范詳解
CommonJS模塊和ES6模塊的區別
Js模塊規范
理解Js模塊化
Require與import的區別
</>復制代碼
“積跬步、行千里”—— 不時的分享更新中~,喜歡留下個贊哦!
往期經典:
團隊合作必備的Git操作
一個頁面從輸入URL到加載顯示完成,發生了什么?
相關好文推薦:
網絡篇—瀏覽器緩存(一)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/113704.html
摘要:依賴全部加載完成后,調用回調函數規范異步加載模塊規范和很相似,簡單,并與和的規范保持了很大的兼容性在規范中,一個模塊就是一個文件。 拋出問題: 在開發中在導入模塊時經常使用require和import; 導出模塊時使用module.exports/exports或者export/export default; 有時候為了引用一個模塊會使用require奇怪的是也可以使用import?...
摘要:當年的加載在沒有前端工程化之前,基本上是我們是代碼一把梭,把所需要的庫和自己的代碼堆砌在一起,然后自上往下的引用就可以了。而且對于前后端的技術要求較高,所以對于項目未必是最有效的方案。 當年的 js 加載 在沒有 前端工程化之前,基本上是我們是代碼一把梭,把所需要的庫和自己的代碼堆砌在一起,然后自上往下的引用就可以了。 那個時代我們沒有公用的cdn,也沒有什么特別好的方法來優化加載j...
摘要:特意對前端學習資源做一個匯總,方便自己學習查閱參考,和好友們共同進步。 特意對前端學習資源做一個匯總,方便自己學習查閱參考,和好友們共同進步。 本以為自己收藏的站點多,可以很快搞定,沒想到一入匯總深似海。還有很多不足&遺漏的地方,歡迎補充。有錯誤的地方,還請斧正... 托管: welcome to git,歡迎交流,感謝star 有好友反應和斧正,會及時更新,平時業務工作時也會不定期更...
閱讀 1063·2021-11-12 10:34
閱讀 993·2021-09-30 09:56
閱讀 671·2019-08-30 15:54
閱讀 2607·2019-08-30 11:14
閱讀 1472·2019-08-29 16:44
閱讀 3210·2019-08-29 16:35
閱讀 2497·2019-08-29 16:22
閱讀 2446·2019-08-29 15:39
极致性价比!云服务器续费无忧!
Tesla A100/A800、Tesla V100S等多种GPU云主机特惠2折起,不限台数,续费同价。
NVIDIA RTX 40系,高性价比推理显卡,满足AI应用场景需要。
乌兰察布+上海青浦,满足东推西训AI场景需要