<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] # 概述 在 ES6 之前,社區制定了一些模塊加載方案,最主要的有 CommonJS 和 AMD 兩種。前者用于服務器,后者用于瀏覽器。ES6 在語言標準的層面上,實現了模塊功能,而且實現得相當簡單,完全可以取代 CommonJS 和 AMD 規范,成為瀏覽器和服務器通用的模塊解決方案。 <br> ES6 模塊的設計思想是盡量的靜態化,使得編譯時就能確定模塊的依賴關系,以及輸入和輸出的變量。CommonJS 和 AMD 模塊,都只能在運行時確定這些東西。比如,CommonJS 模塊就是對象,輸入時必須查找對象屬性。 ``` // CommonJS模塊 let { stat, exists, readFile } = require('fs'); // 等同于 let _fs = require('fs'); let stat = _fs.stat; let exists = _fs.exists; let readfile = _fs.readfile; ``` 上面代碼的實質是整體加載fs模塊(即加載fs的所有方法),生成一個對象(_fs),然后再從這個對象上面讀取 3 個方法。這種加載稱為“運行時加載”,因為只有運行時才能得到這個對象,導致完全沒辦法在編譯時做“靜態優化”。 <br> 由于 ES6 模塊是編譯時加載,使得靜態分析成為可能。有了它,就能進一步拓寬 JavaScript 的語法,比如引入宏(macro)和類型檢驗(type system)這些只能靠靜態分析實現的功能。 <br> # 嚴格模式 ES6 的模塊自動采用嚴格模式,不管你有沒有在模塊頭部加上"use strict";。 ``` // index.html <script type=module src="./index.js"></script> // index.js import { ha } from './module1.js'; console.log(ha()) // undefined // module1.js function ha () { return this } export {ha} ``` <br> <br> # export命令 模塊功能主要由兩個命令構成:export和import。export命令用于規定模塊的對外接口,import命令用于輸入其他模塊提供的功能。 <br> 一個模塊就是一個獨立的文件。該文件內部的所有變量,外部無法獲取。如果你希望外部能夠讀取模塊內部的某個變量,就必須使用export關鍵字輸出該變量。 <br> ## 直接導出變量、函數 ``` // profile.js export var firstName = 'Michael'; export function multiply(x, y) { return x * y; }; ``` <br> <br> ## export {...} 導出 在export命令后面,使用大括號指定所要輸出的一組變量。它與前一種寫法(直接放置在var語句前)是等價的,但是應該優先考慮使用這種寫法。因為這樣就可以在腳本尾部,一眼看清楚輸出了哪些變量。 ``` var firstName = 'Michael'; var lastName = 'Jackson'; var year = 1958; export {firstName, lastName, year}; ``` <br> ## as 重命名 使用as關鍵字,重命名了函數v1和v2的對外接口。重命名后,v2可以用不同的名字輸出兩次。 ``` function v1() { ... } function v2() { ... } export { v1 as streamV1, v2 as streamV2, v2 as streamLatestVersion }; ``` <br> ## 對外接口規范 export命令規定的是對外的接口,必須與模塊內部的變量建立一一對應關系。 ``` // 報錯 export 1; // 報錯 var m = 1; export m; // 報錯 function f() {} export f; ``` <br> 上面兩種寫法都會報錯,因為沒有提供對外的接口。第一種寫法直接輸出 1,第二種寫法通過變量m,還是直接輸出 1。1只是一個值,不是接口。正確的寫法是下面這樣。 ``` // 寫法一 export var m = 1; // 寫法二 var m = 1; export {m}; // 寫法三 var n = 1; export {n as m}; // 正確 export function f() {}; // 正確 function f() {} export {f}; ``` <br> ## 動態綁定 export語句輸出的接口,與其對應的值是動態綁定關系,即通過該接口,可以取到模塊內部實時的值。 ``` export var foo = 'bar'; setTimeout(() => foo = 'baz', 500); ``` 上面代碼輸出變量foo,值為bar,500 毫秒之后變成baz。 <br> 這一點與 CommonJS 規范完全不同。CommonJS 模塊輸出的是值的緩存,不存在動態更新。 <br> ## 定義在模塊頂層 export命令可以出現在模塊的任何位置,只要處于模塊頂層就可以。如果處于塊級作用域內,就會報錯,下一節的import命令也是如此。這是因為處于條件代碼塊之中,就沒法做靜態優化了,違背了 ES6 模塊的設計初衷。 ``` function foo() { export default 'bar' // SyntaxError } foo() ``` <br> <br> # import命令 import命令接受一對大括號,里面指定要從其他模塊導入的變量名。大括號里面的變量名,必須與被導入模塊對外接口的名稱相同。 ``` // main.js import {firstName, lastName, year} from './profile.js'; ``` ## 重命名 如果想為輸入的變量重新取一個名字,import命令要使用as關鍵字,將輸入的變量重命名。 ``` import { lastName as surname } from './profile.js'; ``` ## 改寫 import命令輸入的變量都是只讀的,因為它的本質是輸入接口。也就是說,不允許在加載模塊的腳本里面,改寫接口。 ``` import {a} from './xxx.js' a = {}; // Syntax Error : 'a' is read-only; ``` <br> 上面代碼中,腳本加載了變量a,對其重新賦值就會報錯,因為a是一個只讀的接口。但是,如果a是一個對象,改寫a的屬性是允許的。 ``` import {a} from './xxx.js' a.foo = 'hello'; // 合法操作 ``` <br> 上面代碼中,a的屬性可以成功改寫,并且其他模塊也可以讀到改寫后的值。不過,這種寫法很難查錯,建議凡是輸入的變量,都當作完全只讀,輕易不要改變它的屬性。 <br> ## 提升 import命令具有提升效果,會提升到整個模塊的頭部,首先執行。 ``` foo(); import { foo } from 'my_module'; ``` <br> 上面的代碼不會報錯,因為import的執行早于foo的調用。這種行為的本質是,import命令是編譯階段執行的,在代碼運行之前。 <br> ## 靜態執行 由于import是靜態執行,所以不能使用表達式和變量,這些只有在運行時才能得到結果的語法結構。 ``` // 報錯 import { 'f' + 'oo' } from 'my_module'; // 報錯 let module = 'my_module'; import { foo } from module; // 報錯 if (x === 1) { import { foo } from 'module1'; } else { import { foo } from 'module2'; } ``` <br> ## 其他 最后,import語句會執行所加載的模塊,因此可以有下面的寫法。 ``` import 'lodash'; ``` 上面代碼僅僅執行lodash模塊,但是不輸入任何值。 <br> 如果多次重復執行同一句import語句,那么只會執行一次,而不會執行多次。 ``` import 'lodash'; import 'lodash'; ``` 上面代碼加載了兩次lodash,但是只會執行一次。 <br> ``` import { foo } from 'my_module'; import { bar } from 'my_module'; // 等同于 import { foo, bar } from 'my_module'; ``` 上面代碼中,雖然foo和bar在兩個語句中加載,但是它們對應的是同一個my_module實例。也就是說,import語句是 Singleton 模式。 <br> ## 模塊的整體加載 除了指定加載某個輸出值,還可以使用整體加載,即用星號(*)指定一個對象,所有輸出值都加載在這個對象上面。 ``` // circle.js export function area(radius) { return Math.PI * radius * radius; } export function circumference(radius) { return 2 * Math.PI * radius; } import * as circle from './circle'; console.log('圓面積:' + circle.area(4)); console.log('圓周長:' + circle.circumference(14)); ``` <br> <br> # export default 命令 export default命令用于指定模塊的默認輸出。顯然,一個模塊只能有一個默認輸出,因此export default命令只能使用一次。所以,import命令后面才不用加大括號,因為只可能唯一對應export default命令。 <br> ``` // export-default.js export default function foo() { console.log('foo'); } // 或者寫成 function foo() { console.log('foo'); } export default foo; ``` foo函數的函數名foo,在模塊外部是無效的。加載的時候,視同匿名函數加載。 <br> 本質上,export default就是輸出一個叫做default的變量或方法,然后系統允許你為它取任意名字。 ``` // export-default.js export default function foo() { console.log('foo'); } // 或者寫成 function foo() { console.log('foo'); } export default foo; ``` <br> 其他模塊加載該模塊時,import命令可以為該匿名函數指定任意名字。 這時import命令后面,不使用大括號。 ``` // import-default.js import customName from './export-default'; customName(); // 'foo' ``` <br> 同樣地,因為export default命令的本質是將后面的值,賦給default變量,所以可以直接將一個值寫在export default之后。 ``` // 錯誤 export 42; // 錯誤 export default var a = 1; // 正確 export var a = 1; // 正確 export default 42; // 正確 var a = 1; export default a; ``` # export 與 import 的復合寫法 如果在一個模塊之中,先輸入后輸出同一個模塊,import語句可以與export語句寫在一起。 ``` export { foo, bar } from 'my_module'; // 可以簡單理解為 import { foo, bar } from 'my_module'; export { foo, bar }; ``` <br> 上面代碼中,export和import語句可以結合在一起,寫成一行。但需要注意的是,寫成一行以后,foo和bar實際上并沒有被導入當前模塊,只是相當于對外轉發了這兩個接口,導致當前模塊不能直接使用foo和bar。 <br> 模塊的接口改名和整體輸出,也可以采用這種寫法。 ``` // 接口改名 export { foo as myFoo } from 'my_module'; // 整體輸出 export * from 'my_module'; ``` # 參考資料 [ECMAScript 6入門](http://es6.ruanyifeng.com/#docs/module)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看