第三十一節(jié): ES6 ESModule

1. Module 模塊化

JavaScript 采用'共享一切'的方式加載代碼, 也就是在ES6 之前, JavaScript中定義的一切都共享同一個(gè)全局作用域, 這樣隨著程序復(fù)雜度提升的同時(shí),也會(huì)帶來(lái)命名沖突等諸多問(wèn)題. 因此ES6的一個(gè)目標(biāo)就是解決作用域問(wèn)題. 也為了使JavaScript 應(yīng)用程序顯得有序, 于是引進(jìn)了模塊

1.1 模塊功能

模塊功能主要由兩個(gè)命令構(gòu)成:export和import湾戳。

export命令用于規(guī)定模塊的對(duì)外接口。

import命令用于輸入其他模塊提供的功能。

一個(gè)模塊就是一個(gè)獨(dú)立的文件荧恍。該文件內(nèi)部的所有變量奸汇,外部無(wú)法獲取沥寥。如果你希望外部能夠讀取模塊內(nèi)部的某個(gè)變量卸察,就必須使用export關(guān)鍵字輸出該變量她倘。

2. 模塊的使用

注意如果需要測(cè)試模塊化需要放到服務(wù)器環(huán)境

  <!-- module模塊化  import導(dǎo)入    -->
  <script src="02.js"></script> <!--  這里只是引入了腳本 -->
  <!-- 在瀏覽器上運(yùn)行的基本上是前端模塊化
在服務(wù)器上運(yùn)行的基本是后端模塊化
后臺(tái)是給內(nèi)部員工使用璧微,用來(lái)添加數(shù)據(jù)的。前臺(tái)給用戶看的帝牡。都是前端
 -->

  <script type="module">
    // module表示模塊化往毡。注意:模塊化只能在服務(wù)器環(huán)境運(yùn)行。服務(wù)器環(huán)境有端口號(hào)靶溜,IP地址开瞭,協(xié)議
    //js的type類型通常是javascript,所以省略罩息,里面就直接寫腳本

    import './01.js'  //  這樣導(dǎo)入js嗤详,只是執(zhí)行了一遍該js文件,拿不到任何數(shù)據(jù)瓷炮,不能使用該js中的變量和函數(shù)
    // console.log(a);   //此時(shí)a是在01.js中定義聲明的葱色,這里沒(méi)法使用。
    //導(dǎo)出模塊:想要使用a娘香,要在定義a的文件里寫上export let a =10; 導(dǎo)出的是模塊對(duì)象苍狰,再回到需要的地方拿到這個(gè)導(dǎo)出的模塊對(duì)象
    // import * as aa from './01.js';    //導(dǎo)入理解:從路徑'./01.js'中導(dǎo)出模塊* ,aa作為這個(gè)模塊的別名
    // console.log(aa);
    // console.log('模塊對(duì)象里的變量a為',aa.a);
    import { a } from './01.js'//導(dǎo)出的簡(jiǎn)單寫法,很像解構(gòu)
    console.log(a);   //很像解構(gòu)因?yàn)榍懊鎻暮竺媸菍?duì)象中拿到a
//對(duì)應(yīng)01.js文件中的代碼
export let a =10;
export let b=20;
2.1. export 導(dǎo)出語(yǔ)法

使用export 關(guān)鍵字將模塊中的一部分代碼暴露給其他模塊, 可以將export 關(guān)鍵字放在任何變量, 函數(shù),類聲明之前, 將其導(dǎo)出

導(dǎo)出模塊

export 東西

2.1.1 export 導(dǎo)出(暴露)

// 單個(gè)導(dǎo)出數(shù)據(jù)(變量)   
export let a = 10;        //導(dǎo)出變量
export let b = 20;
export function add(){    //導(dǎo)出函數(shù)
    return a+b
    }
let c = 'c30'
console.log('這里是01.js')
//整體導(dǎo)出烘绽,一次性導(dǎo)出多個(gè)數(shù)據(jù)
let a = 10;
let b = 20;
let c = 'c30'      
function add(){    
return a+b
}
add()
export {    //不能按照對(duì)象的寫法淋昭,只能數(shù)據(jù)的羅列,類似es6的簡(jiǎn)寫方式
    a,
    b,
    add
}

2.1.2 export`命令輸出函數(shù)或類(class)

// 導(dǎo)出函數(shù)
export function multiply(x, y) {
  return x * y;
};

// 導(dǎo)出類
export class Penson{
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
}

2.1.3 as關(guān)鍵字重命名

通常情況下export 輸出的變量, 函數(shù)或者類就是本來(lái)的名字安接,但是有時(shí),我們可能并不希望使用它們的原始名稱. 此時(shí)就可以通過(guò)as關(guān)鍵字修改導(dǎo)出元素的名稱.

function v1() { ... }
function v2() { ... }

export {
  v1 as streamV1,
  v2 as streamV2,
};

2.1.4 特別注意

需要特別注意的是翔忽,export命令規(guī)定的是對(duì)外的接口

// 報(bào)錯(cuò)
export 1;

// 報(bào)錯(cuò)
var m = 1;
export m;

//正確寫法
// 寫法一
export var m = 1;

// 寫法二
var m = 1;
export {m};

// 寫法三
var n = 1;
export {n as m};

同樣的,function的輸出,也必須遵守這樣的寫法

// 報(bào)錯(cuò)
function f() {}
export f;

// 正確
export function f() {};

// 正確
function f() {}
export {f};

動(dòng)態(tài)綁定

export語(yǔ)句輸出的接口歇式,與其對(duì)應(yīng)的值是動(dòng)態(tài)綁定關(guān)系驶悟,即通過(guò)該接口,可以取到模塊內(nèi)部實(shí)時(shí)的值材失。

  <!-- 動(dòng)態(tài)數(shù)據(jù)導(dǎo)出痕鳍,異步異出 -->
  <!-- 導(dǎo)入文件 -->
  <script type='module'>
    import { a, b } from './01.js';
    console.log(a, b);   //a,b不是新值
  </script>
  
  <!-- 導(dǎo)出文件 -->
  let a = 10;
 let b = 20;
 function add() {
    return a + b
 }
 setTimeout(() => {   //3秒后導(dǎo)出
    a = 100;
    b = 200;
 }, 3000)
 export { a, b, add }

 <!-- 動(dòng)態(tài)數(shù)據(jù)導(dǎo)出,異步異出 -->
   <!-- 導(dǎo)入文件 -->
  <script type='module'>
    import { a, b } from './01.js';
    console.log(a, b);   //a,b不是新值

    setTimeout(()=>{
      console.log(a, b);    //這里的值就是更新的了
    },4000)
  </script>
  
    <!-- 導(dǎo)出文件 -->
  let a = 10;
 let b = 20;
 function add() {
    return a + b
 }
 setTimeout(() => {   //3秒后導(dǎo)出
    a = 100;
    b = 200;
 }, 3000)
 export { a, b, add }
2.1.5 整體導(dǎo)出

發(fā)現(xiàn)導(dǎo)入都是需要花括號(hào)的,如果希望導(dǎo)入不用花括號(hào),那就需要改變導(dǎo)出方式

// 導(dǎo)出時(shí)使用export default
let a;
export default a = 10;

// 導(dǎo)入時(shí)可以不用花括號(hào)
<script type="module">
import a from './modules/1.js'
// 默認(rèn)導(dǎo)出 export default  注意一個(gè)模塊只能有一個(gè)默認(rèn)導(dǎo)出
// export default [ 'a', 'b', 'add' ]  //也可以導(dǎo)出對(duì)象豺憔,函數(shù)等  只能有一個(gè)默認(rèn)導(dǎo)出
//export default function aa(){
//    console.log(111);
//} 

導(dǎo)入文件
  <script type='module'>
    import aa from './01.js';
    console.log(aa);
  </script>
// 同時(shí)有默認(rèn)導(dǎo)出 export default  和變量導(dǎo)出
export let a=10;
export let b =20;
export default function aa(){
    console.log(111);
}

導(dǎo)入文件
  <script type='module'>
    // 導(dǎo)入方法一
    import * as aa from './01.js';
    console.log(aa);
    console.log(aa.a);
    console.log(aa.b);
    console.log(aa.default);
    // 導(dǎo)入方法二
    import def, { a, b } from './01.js';   //大括號(hào)里面的是有名字的额获,外面的是默認(rèn)導(dǎo)出的
    console.log(a);
    console.log(b);
    console.log(def);
  </script>
2.2. 導(dǎo)入模塊

使用export命令定義了模塊的對(duì)外接口以后,其他 JS 文件就可以通過(guò)import命令加載這個(gè)模塊恭应。

引入模塊
import 模塊路徑

    //正常導(dǎo)入
    import * as js01 from './01.js'   
    console.log(js01);   //打印導(dǎo)入的模塊對(duì)象
    console.log(js01.a); //這樣導(dǎo)入的數(shù)據(jù)需要打點(diǎn)才能使用,通常不這么用
    
   //類似解構(gòu)的簡(jiǎn)單的導(dǎo)入方式
    import {a,b,add}from './01.js'  
    console.log(a);  //不用打點(diǎn)耘眨,直接使用
    console.log(a,b); 
    console.log(add());
<script type="module">
    import "./modules/1.js";   // 這種寫法只是相當(dāng)于引入一個(gè)文件昼榛,也叫無(wú)綁定導(dǎo)入
    import {a} from "./modules/1.js"   // 導(dǎo)入模塊中導(dǎo)出的a 
</script>
import {firstName, lastName, year} from './profile';
function setName(element) {
  element.textContent = firstName + ' ' + lastName;
}

上面代碼的import命令,用于加載profile.js文件剔难,并從中輸入變量胆屿。import命令接受一對(duì)大括號(hào),里面指定要從其他模塊導(dǎo)入的變量名偶宫。大括號(hào)里面的變量名非迹,必須與被導(dǎo)入模塊(profile.js)對(duì)外接口的名稱相同。

    import {a,b,add}from './01.js'   
    a =100   //導(dǎo)入的數(shù)據(jù)相當(dāng)于常量const a =10 纯趋,不能隨意再賦值憎兽,會(huì)報(bào)錯(cuò)

2.2.1 as關(guān)鍵字改變量名

//導(dǎo)出文件里的內(nèi)容
let a = 10;
let b = 20;
function add(){
    return a+b
    }
let c = 'c30'
export {
    a as aaa,     //將變量a通過(guò)as改名為aaa,導(dǎo)入時(shí)全部使用aaa
    b,
    add as bdd
}

//導(dǎo)入文件里的內(nèi)容
    import {aaa,b,bdd}from './01.js'   
    console.log(aaa);     //使用as后的變量名
    console.log(b);
    console.log(bdd());

import后面的from指定模塊文件的位置吵冒,可以是相對(duì)路徑纯命,也可以是絕對(duì)路徑,.js后綴可以省略痹栖。

2.2.2 import 提升
注意亿汞,import命令具有提升效果,會(huì)提升到整個(gè)模塊的頭部揪阿,首先執(zhí)行疗我。

// 導(dǎo)入前引用
export let a =10;

 導(dǎo)入文件
   <script type='module'>
    console.log('我在導(dǎo)入之前的', a * a);   //導(dǎo)入前引用
    import { a } from './01.js';  //程序會(huì)將import提升,但最好自己寫在最前面
  </script>
foo();

import { foo } from 'my_module';
//import的執(zhí)行早于foo的調(diào)用南捂。這種行為的本質(zhì)是吴裤,import命令是編譯階段執(zhí)行的,在代碼運(yùn)行之前黑毅。

2.2.3 import不能使用表達(dá)式
由于import是靜態(tài)執(zhí)行嚼摩,所以不能使用表達(dá)式和變量,這些只有在運(yùn)行時(shí)才能得到結(jié)果的語(yǔ)法結(jié)構(gòu)。

// 報(bào)錯(cuò)   不能拆成表達(dá)式
import { 'f' + 'oo' } from 'my_module';

// 報(bào)錯(cuò)  導(dǎo)入不能使用表達(dá)式
let module = 'my_module';  
import { foo } from module;

// 報(bào)錯(cuò)   import只能使用在頂層
if (x === 1) {
  import { foo } from 'module1';
} else {
  import { foo } from 'module2';
}

import { foo } from 'my_module';
import { bar } from 'my_module';

// 等同于
import { foo, bar } from 'my_module';

2.2.4 模塊化整體加載

除了指定加載某個(gè)輸出值枕面,還可以使用整體加載愿卒,即用星號(hào)(*)指定一個(gè)對(duì)象,所有輸出值都加載在這個(gè)對(duì)象上面潮秘。

注意琼开,模塊整體加載所在的那個(gè)對(duì)象,不允許運(yùn)行時(shí)改變枕荞。下面的寫法都是不允許的柜候。

2.2.5 import 特點(diǎn)總結(jié)

  1. 可以是相對(duì)路徑也可以是絕對(duì)路徑
    import "./modules/1.js";
  2. import模塊只會(huì)導(dǎo)入一次,無(wú)論你引入多少次。模塊的導(dǎo)入導(dǎo)出有緩存機(jī)制躏精,只有第一次導(dǎo)入會(huì)執(zhí)行一遍并且將數(shù)據(jù)放入緩存渣刷,后面的所有的導(dǎo)入直接到緩存中取數(shù)據(jù)使用,但不會(huì)再執(zhí)行了矗烛。
  3. import "./modules/1.js"; 如果這么用,就相當(dāng)于引入了一個(gè)js文件
  4. 導(dǎo)入模塊中的一個(gè)變量或常量
import {a,b,c} from "./modules/1.js"

5.導(dǎo)入時(shí)可以取別名使用

// 導(dǎo)入時(shí)也可以修改別名
export let a =0;

導(dǎo)入的文件
  <script type='module'>
    let a = 1234;//導(dǎo)入的變量與模塊中的變量a重名了
    console.log('a還是原來(lái)的a',a);   //a已經(jīng)存在辅柴,所以要改別名
    import {a as aa} from './01.js'; 
    console.log('aa是導(dǎo)入時(shí)修改的別名',aa); 
  </script>
import {a as aa,b as bb,c as cc} from "./modules/1.js"

6.導(dǎo)入這個(gè)模塊導(dǎo)出的對(duì)象

import * as obj from './modules/1.js';
// 這個(gè)時(shí)候你就以使用obj這個(gè)Module對(duì)象了
console.log(obj.a);

7.import 的導(dǎo)入語(yǔ)句會(huì)進(jìn)行提升,提升到最頂部,首先執(zhí)行

console.log(a + b);   // 能正常獲取到a,b的值
import {a,b} from './1.js'

8.出去的模塊內(nèi)容,如果里面有定時(shí)器發(fā)生導(dǎo)出內(nèi)容的改變,改變的內(nèi)容會(huì)根據(jù)定時(shí)器自動(dòng)同步緩存中的內(nèi)容,所以外邊導(dǎo)入的內(nèi)容也會(huì)實(shí)時(shí)發(fā)生改變,不像Comment會(huì)緩存瞭吃。

2.2.6 import() 動(dòng)態(tài)引入

默認(rèn)的import語(yǔ)法不能寫在if之類的判斷里的,因?yàn)槭庆o態(tài)引入,先引入在使用

// 這種寫法是錯(cuò)的
let a = 12;
if(a == 12){
    import {a} from './1.js'
}else{
    import {a} from './2.js'
}

import()是動(dòng)態(tài)引入 類似于node里面的require

  //動(dòng)態(tài)導(dǎo)入模塊(按需導(dǎo)入)import()返回promise
  let flag=false;
  if(flag){
    import('./01.js')
    .then(data=>{
      console.log('data',data);
    })
  }else{
    import('./02.js')
    .then(res=>{
      console.log('res',res);
    })
  }

  //動(dòng)態(tài)導(dǎo)入模塊返回promise優(yōu)化寫法
    let flag = true;
    let url = flag ? './01.js' : './02.js'
    import(url)
      .then(res => {
        console.log('res', res);
      })

優(yōu)點(diǎn):

  1. 按需加載
  2. 可以寫在if里面,判斷加載
  3. 路徑都可以是動(dòng)態(tài)的

例子:

/ 這里是1.js
let a = 20;
let b = 30;
export {
  a, b
}

// 這里是2.js
import { a, b } from './1.js';
console.log(`a的值是:${a}, b的值是:$碌嘀`);

const sum = () => {
  console.log(`我是a,b的和:${a + b}`);
  return a + b;
}
const show = () => {
  console.log('show 執(zhí)行了')
  return 1;
}

function Person(name, age) {
  this.name = name;
  this.age = age;
  this.showName = function () {
    return `我的名字是${this.name}`;
  }
}

export {
  sum,
  show,
  a,
  b
}
export default { Person }

// 這里是HTML導(dǎo)入
import mod, { sum, show, a, b } from "./2.js"
console.log(mod);

let p = new mod.Person("wuwei", 18);
console.log(p);
console.log(p.showName());

show();

sum();

console.log(a, b);
// 所有導(dǎo)出只能在頂層導(dǎo)出
if(true){    
    export let a=10;    //這不是頂層所以報(bào)錯(cuò),不能通過(guò)條件判斷和函數(shù)再導(dǎo)出歪架,嵌套導(dǎo)出會(huì)報(bào)錯(cuò)
}else{
    export let a=200;
}

導(dǎo)入文件
  <script type='module'>
    import {a} from './01.js';   //大括號(hào)里面的是有名字的股冗,外面的是默認(rèn)導(dǎo)出的
    console.log(a); 
  </script>
// 導(dǎo)出只能在頂層導(dǎo)出,可以這樣寫
let a =0;
if(true){    
    a=10;    
}else{
    a=200;
}
export{a}    //整體導(dǎo)出才可以

導(dǎo)入文件
  <script type='module'>
    import {a} from './01.js';   //大括號(hào)里面的是有名字的和蚪,外面的是默認(rèn)導(dǎo)出的
    console.log(a); 
  </script>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末止状,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子惠呼,更是在濱河造成了極大的恐慌导俘,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剔蹋,死亡現(xiàn)場(chǎng)離奇詭異旅薄,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)泣崩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門少梁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人矫付,你說(shuō)我怎么就攤上這事凯沪。” “怎么了买优?”我有些...
    開(kāi)封第一講書人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵妨马,是天一觀的道長(zhǎng)挺举。 經(jīng)常有香客問(wèn)我,道長(zhǎng)烘跺,這世上最難降的妖魔是什么湘纵? 我笑而不...
    開(kāi)封第一講書人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮滤淳,結(jié)果婚禮上梧喷,老公的妹妹穿的比我還像新娘。我一直安慰自己脖咐,他們只是感情好铺敌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著屁擅,像睡著了一般偿凭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上煤蹭,一...
    開(kāi)封第一講書人閱讀 51,198評(píng)論 1 299
  • 那天笔喉,我揣著相機(jī)與錄音,去河邊找鬼硝皂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛作谭,可吹牛的內(nèi)容都是我干的稽物。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼折欠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼贝或!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起锐秦,我...
    開(kāi)封第一講書人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤咪奖,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后酱床,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體羊赵,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年扇谣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了昧捷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡罐寨,死狀恐怖靡挥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸯绿,我是刑警寧澤跋破,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布簸淀,位于F島的核電站,受9級(jí)特大地震影響毒返,放射性物質(zhì)發(fā)生泄漏租幕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一饿悬、第九天 我趴在偏房一處隱蔽的房頂上張望令蛉。 院中可真熱鬧,春花似錦狡恬、人聲如沸珠叔。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至兔乞,卻和暖如春汇鞭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背庸追。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工霍骄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人淡溯。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓读整,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親咱娶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子米间,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

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

  • 1. Module 模塊化 JavaScript 采用'共享一切'的方式加載代碼, 也就是在ES6 之前, Jav...
    時(shí)光如劍閱讀 871評(píng)論 0 7
  • 原本想稍微整理一下 ES 新特性,沒(méi)想到花了相當(dāng)多的時(shí)間膘侮,本文也巨長(zhǎng)屈糊,依然推薦使用 簡(jiǎn)悅[https://gith...
    401閱讀 1,871評(píng)論 0 5
  • 系列文章導(dǎo)航 模塊(一) CommonJs,AMD, CMD, UMD 本文參考阮一峰 ES6入門 Module的...
    合肥黑閱讀 6,116評(píng)論 0 4
  • 1、es5和es6的區(qū)別琼了,說(shuō)一下你所知道的es6 ECMAScript5逻锐,即ES5,是ECMAScript的第五次...
    沒(méi)糖_cristalle閱讀 684評(píng)論 0 0
  • 學(xué)習(xí)vue的語(yǔ)法之前表伦,首先要掌握一些ES6的新語(yǔ)法谦去,以便更容易理解vue中的一些編程風(fēng)格。 1. 變量與常量的聲明...
    yangsg閱讀 801評(píng)論 0 3