[深入12] 前端模塊化

image

導(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ù)

[react] Hooks

[部署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í)行順序問題
image

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>


    image
  • 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
    
微信圖片_20210323232128.jpg

模塊化的發(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)衡全局變量污染問題淑廊,可以使用特殊符號避免
用 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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市攀圈,隨后出現(xiàn)的幾起案子暴凑,更是在濱河造成了極大的恐慌,老刑警劉巖量承,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搬设,死亡現(xiàn)場離奇詭異,居然都是意外死亡撕捍,警方通過查閱死者的電腦和手機拿穴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來忧风,“玉大人默色,你說我怎么就攤上這事∈ㄍ龋” “怎么了腿宰?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長缘厢。 經(jīng)常有香客問我吃度,道長,這世上最難降的妖魔是什么贴硫? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任椿每,我火速辦了婚禮,結(jié)果婚禮上英遭,老公的妹妹穿的比我還像新娘间护。我一直安慰自己,他們只是感情好挖诸,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布汁尺。 她就那樣靜靜地躺著,像睡著了一般多律。 火紅的嫁衣襯著肌膚如雪痴突。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天菱涤,我揣著相機與錄音苞也,去河邊找鬼。 笑死粘秆,一個胖子當(dāng)著我的面吹牛如迟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼殷勘,長吁一口氣:“原來是場噩夢啊……” “哼此再!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起玲销,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤输拇,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后贤斜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體策吠,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年瘩绒,在試婚紗的時候發(fā)現(xiàn)自己被綠了猴抹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡锁荔,死狀恐怖蟀给,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情阳堕,我是刑警寧澤跋理,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站恬总,受9級特大地震影響前普,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜壹堰,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一汁政、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缀旁,春花似錦、人聲如沸勺鸦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽换途。三九已至懊渡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間军拟,已是汗流浹背剃执。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留懈息,地道東北人肾档。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親怒见。 傳聞我的和親對象是個殘疾皇子俗慈,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容