導(dǎo)航
[深入01] 執(zhí)行上下文
[深入02] 原型鏈
[深入03] 繼承
[深入04] 事件循環(huán)
[深入05] 柯里化 偏函數(shù) 函數(shù)記憶
[深入06] 隱式轉(zhuǎn)換 和 運算符
[深入07] 瀏覽器緩存機制(http緩存機制)
[深入08] 前端安全
[深入09] 深淺拷貝
[深入10] Debounce Throttle
[深入11] 前端路由
[深入12] 前端模塊化
[深入13] 觀察者模式 發(fā)布訂閱模式 雙向數(shù)據(jù)綁定
[深入14] canvas
[深入15] webSocket
[深入16] webpack
[深入17] http 和 https
[深入18] CSS-interview
[深入19] 手寫Promise
[深入20] 手寫函數(shù)
[部署01] Nginx
[部署02] Docker 部署vue項目
[部署03] gitlab-CI
[源碼-webpack01-前置知識] AST抽象語法樹
[源碼-webpack02-前置知識] Tapable
[源碼-webpack03] 手寫webpack - compiler簡單編譯流程
[源碼] Redux React-Redux01
[源碼] axios
[源碼] vuex
[源碼-vue01] data響應(yīng)式 和 初始化渲染
前置知識
js中省略每行結(jié)尾的 ; 分號時赋元,需要注意的問題
- <font color=red>() 小括號開頭的前一條語句杂腰,小括號前必須加分號,或者在前一條語句結(jié)束時加分號</font>
- <font color=red>[] 中括號開頭的前一條語句忙干,中括號前必須加分號,或者在前一條語句結(jié)束時加分號</font>
js中省略每行結(jié)尾的 ; 分號懈玻,需要注意的問題:
- () 小括號開頭的前一條語句巧婶,小括號前必須加分號,或者在前一條語句結(jié)束時加分號
- [] 中括號開頭的前一條語句涂乌,中括號前必須加分號艺栈,或者在前一條語句結(jié)束時加分號
例子:
(1) () 小括號開頭的前一條語句,小括號前要加 ';' 分號湾盒,或者前一條語句結(jié)尾加分號
var a = 1
(function() { // 報錯:Uncaught TypeError: 1 is not a function
console.log(a)
})()
解決方法:
var a = 1
;(function() { <---------
// 在()前加分號
// 或者在 var a = 1; 結(jié)尾加分號
console.log(a)
})()
(2) [] 中括號開頭的前一條語句湿右,需要在[]前面加上 ';' 分號,或者前一條語句結(jié)尾加分號
var a = 1
[1,2,3].forEach(item => console.log(item)) // Uncaught TypeError: Cannot read property 'forEach' of undefined
解決方法:
var a = 1
;[1,2,3].forEach(item => console.log(item)) <---------
作用域
- 作用域:指變量存在的范圍
- 作用域分為:<font color=red>全局作用域罚勾,函數(shù)作用域毅人,eval</font>
<script>
var a = 1
var c = 2
function x() {
var a = 10 // 全局中也有a,但是函數(shù)作用域聲明的a不會影響全局
var b = 100
c = 20 // 但是函數(shù)內(nèi)部能修改全局的變量尖殃,(作用域鏈內(nèi)部能修改外部的變量)
}
x()
console.log(a) // 1
console.log(c) // 20
;(function() { // 注意分號是必須的丈莺,因為()[]開頭的前一條語句末尾,或者()[]開頭加 ;
console.log(c) // 20
})()
console.log(b) // 報錯送丰,b is not defined 函數(shù)外部不能訪問函數(shù)內(nèi)部的變量
</script>
瀏覽器解析js文件的流程
瀏覽器加載 javascript 腳本缔俄,主要通過script標(biāo)簽
來完成
- (1) 瀏覽器一邊下載html文件,一邊開始解析
就是說:不等到html下載完成器躏,就開始解析
- (2) 解析過程中俐载,遇到script標(biāo)簽就暫定解析,把網(wǎng)頁的渲染控制權(quán)交給javascript引擎
- (3) 如果script標(biāo)簽引用了
外部腳本
登失,則下載腳本并執(zhí)行
遏佣;如果沒有
就直接執(zhí)行
script標(biāo)簽內(nèi)的代碼 - (4) javascript引擎
執(zhí)行完畢
,控制權(quán)交還渲染引擎
揽浙,恢復(fù)解析html網(wǎng)頁
瀏覽器解析js文件流程
總結(jié):
1. html是一邊下載状婶,一邊解析的
2. script標(biāo)簽會阻塞html解析意敛,如果耗時較長,就會出現(xiàn)瀏覽器假死現(xiàn)象
3. script標(biāo)簽之所以會阻止html解析太抓,阻止渲染頁面空闲,是因為js可能會修改DOM樹和CSSOM樹,造成復(fù)雜的線程競賽和控制權(quán)競爭的問題
js同步加載走敌,js異步加載
- <font color=red>同步加載:阻塞頁面</font>
- <font color=red>異步加載:不會阻塞頁面</font>
script標(biāo)簽 異步加載的方式 async defer
defer:是延遲的意思
-
(1) script標(biāo)簽放置在body底部
- 嚴(yán)格說不算異步加載,但是這也是常見的通過改變js加載方式來提升頁面性能的一種方式
-
(2) <font color=red>defer 屬性</font>
異步加載逗噩,不阻塞頁面掉丽,在DOM解析完成后才執(zhí)行js文件
順序執(zhí)行,不影響依賴關(guān)系
-
(3) <font color=red>async 屬性</font>
異步加載异雁,加載不阻塞頁面捶障,但是async會在異步加載完成后,立即執(zhí)行纲刀,如果此時html未加載完项炼,就會阻塞頁面
注意:異步加載,加載不會阻塞頁面示绊,執(zhí)行會阻塞頁面
不能保證各js文件的執(zhí)行順序
<table><tr><td bgcolor=orange> defer (1)加載:是異步加載锭部,加載不阻塞頁面;(2)執(zhí)行:要DOM渲染完才執(zhí)行面褐,能保證各js的執(zhí)行順序</table></tr></td>
<table><tr><td bgcolor=yellow>async (1)加載:是異步加載拌禾,加載不阻塞頁面;(2)執(zhí)行:加載完立即執(zhí)行展哭,不能保證各js的執(zhí)行順序</table></tr></td bgcolor=orange>
-
<font color=red>defer湃窍,async,放在body底部匪傍,三種方法哪種好您市?</font>
- 最穩(wěn)妥的辦法還是把
<script>
寫在<body>
底部,沒有兼容性問題役衡,沒有白屏問題茵休,沒有執(zhí)行順序問題
- 最穩(wěn)妥的辦法還是把
tree命令 - 生成目錄結(jié)構(gòu)
tree [<Drive>:][<Path>] [/f] [/a]
tree命令生成目錄結(jié)構(gòu)
tree [<Drive>:][<Path>] [/f] [/a]
/f:顯示每個目錄中文件的名稱
/a:使用文本字符而不是圖形字符連接
例子:
C:.
│ index.html
│
├─a
│ └─b
│ ccc.js
│
└─requirejs
a.js
b.js
c.js
立即調(diào)用的函數(shù)表達(dá)式 IIFE
IIFE Immediately-invoked Function Expressions 立即調(diào)用的函數(shù)表達(dá)式
(function(){...})()
,(function(){...}())
- 需求:在函數(shù)定義后映挂,立即調(diào)用該函數(shù)
- 出現(xiàn)問題:<font color=red>如果直接在函數(shù)后面加上括號去調(diào)用泽篮,就會報錯 </font>
報錯:function(){}();
- 報錯原因:<font color=red>function關(guān)鍵詞出現(xiàn)在行首,會被js解析成語句( 即函數(shù)的定義 )柑船,不應(yīng)該以圓括號結(jié)尾帽撑,所以報錯</font>
- 如何解決:IIFE 利用立即調(diào)用的函數(shù)表達(dá)式去解決
- 即讓其成為一個表達(dá)式,而不是語句
- <font color=red>語句不能以圓括號結(jié)尾鞍时,但是表達(dá)式可以 </font>
- 需要掌握的知識點:
(1) IIFE如何傳參
(2) 多個IIFE一起時亏拉,分號不能省略
(3) IIFE不會污染全局變量扣蜻,因為不用為函數(shù)命名
(4) IIFE可以形成一個單獨的作用域名,則可以封裝一些外部無法讀取的變量
(5) IIFE的兩種寫法
IIFE 立即調(diào)用的函數(shù)表達(dá)式
需要理解的幾個方面:
(1) IIFE如何傳參 - (作為模塊時及塘,依賴項就是通過參數(shù)傳遞實現(xiàn)的)
(2) 多個IIFE一起時莽使,分號不能省略
(3) IIFE不會污染全局變量,因為不用為函數(shù)命名
(4) IIFE可以形成一個單獨的作用域名笙僚,則可以封裝一些外部無法讀取的變量
(5) IIFE的兩種寫法
---------------
案例:
const obj = {
name: 'woow_wu7'
};
(function(params) { // params形參
console.log(obj) // 這里訪問的obj芳肌,不是函數(shù)參數(shù)傳入的,而是訪問的父級作用域的obj
console.log(params)
})(obj); // obj是實參
// (1)
// 注意:這里末尾的分號是必須的肋层,因為是兩個IIFE連續(xù)調(diào)用
// 打右隗浴:都是 { name: 'woow_wu7' }
// (2)
// IIFE的兩種寫法:
// 1. (function(){...})()
// 2. (function(){...}())
// 上面的(1)(2)都會被js理解為表達(dá)式,而不是語句
// 表達(dá)式可以以圓括號結(jié)尾栋猖,函數(shù)定義語句不能以圓括號結(jié)尾
// (3)
// 因為function沒有函數(shù)名净薛,避免了變量名污染全局變量
(function(params2){
console.log(obj)
console.log(params2)
}(obj))
前端模塊化
模塊的概念
- 將一個復(fù)雜程序的各個部分,按照一定的
規(guī)則(規(guī)范)
封裝不同的塊(不同的文件)
蒲拉,并組合在一起 - <font color=red>塊 內(nèi)部的變量和方法是私有的肃拜,只會向外暴露一些接口,通過接口與外部進行通信</font>
非模塊化存在的問題
- 對全局變量的污染
- 各個js文件內(nèi)部變量互相修改雌团,即只存在全局作用域燃领,沒有函數(shù)作用域
- 各個模塊如果存在依賴關(guān)系,依賴關(guān)系模糊辱姨,很難分清誰依賴誰柿菩,而依賴又必須前置
- 難以維護
<!DOCTYPE html>
<html lang="en">
<head>
<script>
var me = 'changeMe';
console.log(window.me, '全局變量未被修改前的window.me') // changeMe
</script>
<script src="./home.js"></script> <!-- var home = 'chongqing' -->
<script src="./me.js"></script> <!-- var me = 'woow_wu7' -->
<script src="./map.js"></script> <!-- var map = 'baidu' -->
</head>
<body>
<script>
console.log(window.me, '全局變量被修改后的window.me') // 'woow_wu7' 說明污染了全局變量
console.log(map, '模塊內(nèi)變量map被修改前') // baidu
var map = 'Amap'
console.log(map, '別的模塊內(nèi)mao居然被修改了') // Amap 說明模塊內(nèi)的變量被修改了,因為只有全局作用域
</script>
</body>
</html>
模塊化的好處
可以先記憶一下雨涛,有個概念
- 更好的分離:避免一個html放置多個script枢舶,只需引入一個總的script
- 避免命名沖突:模塊內(nèi)的變量不會影響到模塊外,即各個模塊可以有相同命令的變量
- 更好的處理依賴:每個模塊只用擔(dān)心自己所依賴的模塊替久,不用考慮其他模塊的依賴問題凉泄,<font color=red>如果在一個html中引入很多script,各個模塊(script)的依賴關(guān)系是很難分清楚的</font>
- 更利于維護
模塊化需要解決的問題
- 模塊的安全安裝蚯根,即不能污染任何模塊外的代碼
- 唯一的標(biāo)識每個模塊
- 優(yōu)雅的暴露api后众,不能增加任何全局變量
- 可以引用其他依賴
<font color=red>模塊化不同方案對比</font>
IIFE,CommonJS規(guī)范颅拦,AMD蒂誉,CMD,ES6的模塊化方案
commonjs -------------------------------- node.js使用的規(guī)范
AMD:Asynchronous Module Definition ----- 異步模塊定義
CMD:Common Module Definition ----------- 通用模塊定義
- <table><tr><td bgcolor=orange>commonjs用于服務(wù)端距帅,同步加載 ------------------------------ node.js使用的標(biāo)準(zhǔn)</tr></td></table>
- <table><tr><td bgcolor=orange>AMD和CMD主要用于瀏覽器端右锨,異步加載</tr></td></table>
- <table><tr><td bgcolor=orange>ES6的模塊方案:用于瀏覽器和服務(wù)器,通用方案碌秸,靜態(tài)化</tr></td></table>
- <table><tr><td bgcolor=yellow>AMD依賴前置绍移,依賴必須一開始寫好悄窃,提前加載依賴 ( 依賴前置,提前執(zhí)行 ) -------- RequireJS </tr></td></table>
- <table><tr><td bgcolor=yellow>CMD依賴就近蹂窖,需要使用的時候轧抗,才去加載依賴 ( 依賴就近,延時執(zhí)行 ) ------------- seajs</tr></td></table>
-
<table><tr><td bgcolor=yellow>ES6模塊是靜態(tài)化的瞬测,在 ( 編譯時) 就能確定模塊得依賴關(guān)系横媚,輸入,輸出涣楷;而AMD和CMD只能在運行時才能確定</tr></td></table>
-
2021/3/23補充
- ES6的模塊化方案 =>
動態(tài)更新
- CommonJS =>
模塊輸入的是 ( 值的緩存 )分唾,不存在動態(tài)更新
-
ES6的模塊中
- export { a, b }; export后面的花括號并不是對象,而是一個接口狮斗,這個接口中有 a 和 b 兩個變量
-
CommonJS中
- module.export = {a: 1}; 導(dǎo)出的就是一個對象
es6模塊 ------- export var foo = 'bar'; setTimeout(() => foo = 'baz', 500); 上面代碼輸出變量foo,值為bar弧蝇,500 毫秒之后變成baz
- ES6的模塊化方案 =>
模塊化的發(fā)展歷程
(1)原始階段 - 只用函數(shù)作用域
var a1 = 'a1'
function a1() {}
function a2() {}
缺點: 函數(shù)名會污染全局變量
(2)對象封裝
var a3 = 'a3'
var a1 = {
a2: function() {}
a3: function() {}
}
優(yōu)點:
1. a1對象的a3屬性不會污染全局變量a3
2. 減少了全局作用域內(nèi)的變量數(shù)量:
- 這里只有a3碳褒,a1 ------- 2個
- 而全用函數(shù):---------- 3個
缺點:
1. 還是會污染全局變量
2. 外部可以修改a1的屬性,即會暴露所有屬性并且可以被外部修改
(3)用 IIFE(立即調(diào)用的函數(shù)表達(dá)式) 實現(xiàn)模塊化
IIFE Immediately-invoked Function Expressions
- IIFE實現(xiàn)的模塊化能解決的問題:
- <font color=red>在其他地方都要不能修改模塊內(nèi)部的變量</font>
- 不能在其他地方修改模塊內(nèi)的變量看疗,說明每個模塊都有自己的( <font color=red>單獨的作用域</font> )沙峻,<font color=red>外部無法訪問</font>
- 函數(shù)就具有( <font color=red>函數(shù)作用域</font> ),函數(shù)外部無法訪問函數(shù)內(nèi)部的變量
- <font color=red>模塊內(nèi)的變量不能污染全局變量</font>
- 即模塊內(nèi)的變量的作用域不能是( 全局作用域 )两芳,則可以用函數(shù)來解決( 函數(shù)作用域 )
- 什么叫不能污染全局變量:
- 即不能變量覆蓋摔寨,模塊內(nèi)的變量不能覆蓋全局的變量,從而影響全局變量
- <font color=red>避免直接使用函數(shù)怖辆,函數(shù)名污染全局變量 </font>
- <font color=red>IIFE實現(xiàn)的模塊化是复,依賴其他模塊,可用傳參來解決</font>
- <font color=red>模塊需要暴露的方法和變量竖螃,都可以掛載都window上</font> =>
權(quán)衡全局變量污染問題淑廊,可以使用特殊符號避免
- <font color=red>在其他地方都要不能修改模塊內(nèi)部的變量</font>
用 IIFE(立即調(diào)用的函數(shù)表達(dá)式) 實現(xiàn)模塊化
需要解決的問題:
(1) 各個模塊中定義的變量不能在模塊外被修改,只能在該模塊內(nèi)修改特咆,則每個模塊需要形成單獨的作用域
(2) 模塊內(nèi)的變量不能污染全局變量 => 即不能在同一個作用域季惩,用函數(shù)可以解決
------
未解決以上問題前的模塊:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
var me = 'changeMe';
console.log(window.me, '全局變量未被修改前的window.me') // changeMe
</script>
<script src="./home.js"></script> <!-- var home = 'chongqing' -->
<script src="./me.js"></script> <!-- var me = 'woow_wu7' -->
<script src="./map.js"></script> <!-- var map = 'baidu' -->
</head>
<body>
<script>
console.log(window.me, '全局變量被修改后的window.me') // 'woow_wu7' 說明污染了全局變量
console.log(map, '模塊內(nèi)變量map被修改前') // baidu
var map = 'Amap'
console.log(map, '別的模塊內(nèi)mao居然被修改了') // Amap 說明模塊內(nèi)的變量被修改了
</script>
</body>
</html>
------
IIFE實現(xiàn)的模塊化:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
(function(window,$) {
var me = 'changeMe';
console.log(me) // changeMe
window.me = me
})(window, jquery)
// 該模塊依賴jquery
// 需要暴露的變量,可以掛載到window對象上
</script>
</head>
<body>
<script>
console.log(me, '外部無法訪問腻格,報錯')
// me is not defined
</script>
</body>
</html>
(4)CommonJS規(guī)范
- <font color=red>Nodejs采用CommonJS規(guī)范画拾,主要用于服務(wù)端,同步加載</font>
- 同步加載
- nodejs主要用服務(wù)端菜职,加載的模塊文件一般都存在硬盤上青抛,加載起來比加快,不用考慮異步加載的方式
- 但如果是瀏覽器環(huán)境些楣,要從服務(wù)器加載模塊脂凶,就必須采用異步方式宪睹,所以就有了AMD CMD 方案
- <font color=red>module表示當(dāng)前模塊,module.exports是對外的接口蚕钦,require一個模塊其實就是加載module.exports屬性</font>
- 注意:在node.js中 moudle.exports 和 exports 的區(qū)別亭病?
nodejs中 moudle.exports 和 exports 的區(qū)別
案例:
--- modu.js ---
const a = 11;
module.exports = a ---------------------------------- module.exports 暴露模塊
--- modu2.js ---
const b = 22;
exports.bVar = b ------------------------------------ exports 暴露模塊
--- index.js ---
const a = require('./modu.js') ---------------------- require 引入模塊
const b = require('./modu2.js')
console.log(a, 'a') // 11
console.log(b, 'b') // { bVar: 22 }
console.log(b.bVar, 'b.bVar') // 22
(5) AMD - Asynchronous Module Definition異步模塊定義 <font color=red>// RequireJS</font>
- AMD用于瀏覽器端,異步加載嘶居,依賴前置
- <font color=red>瀏覽器端不能使用commonjs同步加載方案</font>
- <font color=red>是因為瀏覽器端加載js的文件在服務(wù)器上罪帖,需要的時間較長,同步加載會阻塞頁面的加載和渲染</font>
- <font color=red>而對于服務(wù)器端邮屁,文件則在硬盤中整袁,加載和讀取都十分快,所以可以同步加載佑吝,不用考慮加載方式</font>
- RequireJS
RequireJS
(1) 目錄結(jié)構(gòu):
C:.
│ index.html
│
└─requirejs
b.js
c.js
(2) 例子
b.js
define(function () { // ----------------- define(function(){...}) 定義一個模塊
return 'string b'
})
c.js
define(['./b.js'], function(res) { // --- define(['a'], function(res){...}) 定義一個有依賴的模塊坐昙,c 依賴模塊 b
return res + 'c'
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdn.bootcss.com/require.js/2.3.6/require.min.js"></script>
</head>
<body>
<script>
require(['./requirejs/c.js'], function(res) { // 引入模塊,并使用模塊暴露的值芋忿,res 就是模塊 c 暴露的值
console.log(res, 'res')
})
</script>
</body>
</html>
(6) CMD - Common Module Definition通用模塊定義 <font color=red>// seajs</font>
- CMD用于瀏覽器端炸客,異步加載,依賴就近戈钢,即使用時才會去加載
- CMD是SeaJS 在推廣過程中對模塊定義的規(guī)范化產(chǎn)出
//定義沒有依賴的模塊
define(function(require, exports, module){
var value = 1
exports.xxx = value
module.exports = value
})
//定義有依賴的模塊
define(function(require, exports, module){
var module2 = require('./module1') //引入依賴模塊(同步)
require.async('./module2', function (m3) { //引入依賴模塊(異步)
})
exports.xxx = value // 暴露模塊痹仙,也可以用module.exports
})
// 引入使用模塊
define(function (require) {
var a = require('./module1')
var b = require('./module2')
})
(7) ES6中的模塊方案
- <font color=red>ES6的模塊化方案作為通用方案,可以用于瀏覽器端和服務(wù)器端</font>
- <font color=red>ES6中的模塊化方案殉了,設(shè)計思想是靜態(tài)化开仰,即在編譯時就能確定模塊的依賴關(guān)系,輸入變量薪铜,輸出變量众弓;而CommonJS和AMD和CMD都只有在運行時才能確定依賴關(guān)系,輸入和輸出</font>
CommonJS模塊就是對象痕囱,輸入時(引入模塊)必須查找對象屬性
- CommonJS是運行時加載田轧,因為只有運行時才能生成對象,從而得到對象鞍恢,才可以訪問對象的值
- ES6模塊不是對象傻粘,而是通過exports顯示輸出的代碼,通過import輸入
- ES6的模塊帮掉,默認(rèn)采用嚴(yán)格模式
// CommonJS模塊
let { stat, exists, readFile } = require('fs');
(1) 實質(zhì)上是整體加載模塊fs弦悉,在fs對象上再去讀取stat,exists等屬性
(2) 像CommonJS這種加載方式成為運行時加載蟆炊,因為只有運行時才能得到這個對象
// ES6模塊
import { stat, exists, readFile } from 'fs';
(1) 實質(zhì)是從fs模塊加載3個方法稽莉,其他方法不加載 - 稱為編譯時加載或者靜態(tài)加載
(2) ES6在編譯時完成加載,而不需要像CommonJS涩搓,AMD污秆,CMD那樣運行時加載劈猪,所以效率較高
- 這會導(dǎo)致沒法引用 ES6 模塊本身,因為它不是對象
// ES6模塊的好處
(1) 靜態(tài)加載良拼,編譯時加載 ----- 效率較高战得,可以實現(xiàn)( 類型檢查 )等只能靠( 靜態(tài)分析 )實現(xiàn)的功能
(2) 不再需要( 對象 )作為( 命名空間 ),未來這些功能可以通過模塊提供
- export 命令
- 模塊的功能主要由兩個命令構(gòu)成:import 和 export
- <font color=red>export 可以輸出變量庸推,函數(shù)常侦,類</font>
- export 輸出的變量,就是變量本來的名字贬媒,但是可以通過 <font color=red>as</font> 關(guān)鍵字來重命名
// 報錯
export 1;
// 報錯
var m = 1;
export m;
// 寫法一
export var m = 1;
// 寫法二
var m = 1;
export {m};
// 寫法三
var n = 1;
export {n as m};
// 報錯
function f() {}
export f;
// 正確
export function f() {};
// 正確
function f() {}
export {f};
- 模塊的整體加載
- 除了指定加載某個輸出值聋亡,還可以使用整體加載。
- 即用 <font color=red>*</font> 指定一個對象际乘,所有輸出值都加載到這個對象上面
- export default
- import 需要直到函數(shù)名或變量命坡倔,否則無法加載, - export default指定模塊的默認(rèn)輸出
- <font color=red>export default 其實時輸出 default 的變量脖含,所以他后面不能跟變量的聲明語句</font>
// 正確
export var a = 1;
// 正確
var a = 1;
export default a; ----------------> export default a : 意思是把變量a賦值給default變量
// 錯誤
export default var a = 1
// 正確
export default 42; ---------------> 注意:可以將值賦值給default變量致讥,對外的接口是 default
// 報錯
export 42; -----------------------> 沒有指定對外的接口
- <font color=red>export 與 import 的復(fù)合寫法</font>
export { foo, bar } from 'my_module';
// 可以簡單理解為
import { foo, bar } from 'my_module';
export { foo, bar };
import()函數(shù) - 支持動態(tài)加載模塊
- 因為ES6模塊化方案是靜態(tài)加載,即編譯時就能確定依賴關(guān)系器赞,輸入,輸出墓拜;不用等到運行時
- <font color=red>那如何做到 動態(tài)加載 ?</font>
- <font color=red>import(specifier) ---------- specifier:說明符</font>
- <font color=red>import()返回一個promise</font>
- import()類似于 Node 的require方法港柜,區(qū)別主要是前者是異步加載,后者是同步加載咳榜。
- 它是<font color=red>運行時執(zhí)行夏醉,也就是說,什么時候運行到這一句涌韩,就會加載指定的模塊畔柔。</font>
import() 語法
(1) 按需加載:在需要的時候,再加載某個模塊
(2) 條件加載:可以根據(jù)不同的條件加載不同的模塊臣樱,比如 if 語句中
(3) 動態(tài)的模塊路徑:允許模塊路徑動態(tài)生成
import(f()).then(...); // 據(jù)函數(shù)f()的返回值靶擦,加載不同的模塊。
(4) import()加載模塊成功以后雇毫,這個模塊會作為一個對象玄捕,當(dāng)作then方法的參數(shù)。
// 因此棚放,可以使用對象解構(gòu)賦值的語法枚粘,獲取輸出接口。
// import('./myModule.js').then(({export1, export2}) => {...});
(5) 如果模塊有default輸出接口飘蚯,可以用參數(shù)直接獲得馍迄。
// import('./myModule.js').then(myModule => {console.log(myModule.default)});
// 上面 myModule 模塊具有defalut接口福也,所以可以用 ( 參數(shù).default ) 獲取
(6) 同時加載多個模塊
Promise.all([
import('./module1.js'),
import('./module2.js'),
import('./module3.js'),
])
.then(([module1, module2, module3]) => {
···
});
資料
詳細(xì) (模塊化) 真的寫得好:https://juejin.im/post/6844903817272623117#heading-0
超完整(模塊化):https://juejin.im/post/6844903744518389768#heading-0
js中哪些情況不能省略分號:https://blog.csdn.net/BigDreamer_/article/details/90230953
ES6模塊化方案:http://es6.ruanyifeng.com/#docs/module
我的語雀:https://www.yuque.com/woowwu/msyqpd/gyys84
模塊化參考資料 https://juejin.cn/post/6844903598480965646