天天看點

ES6 子產品加載export 、import、export default 、import() 文法與差別,筆記總結

ES6子產品加載export 、import、export default 、import() 文法與差別

在 ES6 之前,社群制定了一些子產品加載方案,最主要的有 CommonJS 和 AMD 兩種。

CommonJS 用于伺服器,AMD 用于浏覽器。

ES6 在語言标準層面上,實作了子產品功能,而且簡單,完全可以取代 CommonJS 和 AMD 規範,成為浏覽器和伺服器通用的子產品解決方案。

ES6 的子產品自動采用嚴格模式,不管你有沒有在子產品頭部加上"use strict";。

嚴格模式主要有以下限制。

變量必須聲明後再使用

函數的參數不能有同名屬性,否則報錯

不能使用with語句

不能對隻讀屬性指派,否則報錯

不能使用字首 0 表示八進制數,否則報錯

不能删除不可删除的屬性,否則報錯

不能删除變量delete prop,會報錯,隻能删除屬性delete global[prop]

eval不會在它的外層作用域引入變量

eval和arguments不能被重新指派

arguments不會自動反映函數參數的變化

不能使用arguments.callee

不能使用arguments.caller

禁止this指向全局對象

不能使用fn.caller和fn.arguments擷取函數調用的堆棧

增加了保留字(比如protected、static和interface)

上面這些限制,子產品都必須遵守。由于嚴格模式是 ES5 引入的,不屬于 ES6,是以請參閱相關 ES5 書籍。

其中,尤其需要注意this的限制。ES6 子產品之中,頂層的this指向undefined,即不應該在頂層代碼使用this。

//index.js
//export 指令
            var a = 'a';
            var b = 'b';
            var c = 'c';
            //指令規定的是對外的接口,必須與子產品内部的變量建立一一對應關系。用大括号
            export {
                a,b,c
            }
            export var d = 'd';
            export {d}
            export function f(){}
            export {f}
            //報錯
            export 1;
            // 報錯
            var m = 1;
            export m;
            // 報錯
            function f() {}
            export f;
--------------------------------------------------------------------------------------------
            //export重命名語句 原命名 as 新命名
            export {
                a as m,
                b as n
            }
--------------------------------------------------------------------------------------------
            //export語句輸出的接口,與其對應的值是動态綁定關系,即通過該接口,可以取到子產品内部實時的值。
            //輸出變量foo,值為bar,500 毫秒之後變成baz。
            //這一點與 CommonJS 規範完全不同。CommonJS 子產品輸出的是值的緩存,不存在動态更新
            export var foo = 'bar';
            setTimeout(() => foo = 'baz', 500);
--------------------------------------------------------------------------------------------
            //export指令可以在子產品的任何位置,必須處于子產品頂層,如果在塊級作用域沒法靜态化會報錯。
            //報錯
            function foo() {
                export default 'bar' 
            }
            foo()           
//main.js
//import指令
            import {a} from 'index.js';
            import {b} from 'index.js';
            import {c} from 'index.js';
            //等同于
            import {a,b,c} from 'index';//以上兩種寫法相同,import語句是獨生模式
--------------------------------------------------------------------------------------------
            import {a} from 'index';
            //報錯 變量a是隻讀的,可以改寫a的屬性
            var a = '1';
            //合法操作,但是其他子產品輸入讀到改寫後的值,不推薦使用難以查錯,可用于特殊場景路由控制等等
            var a.foo = 'ok';
--------------------------------------------------------------------------------------------
            //import 有提升效果,會提升到子產品頭部執行
            foo();
            import { foo } from 'my_module';//ok
--------------------------------------------------------------------------------------------
            //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';
            }           
//子產品使用整體加載
            //circle.js
            export function area(radius) {
              return Math.PI * radius * radius;
            }
            export function circumference(radius) {
              return 2 * Math.PI * radius;
            }
                    //index.js
            //逐一加載下面寫法
            import { area, circumference } from './circle';
            console.log('圓面積:' + area(4));
            console.log('圓周長:' + circumference(14));
            //使用整體加載,即用星号(*)指定一個對象,所有輸出值都加載在這個對象上面。
            import * as circle from './circle';
            console.log('圓面積:' + circle.area(4));
            console.log('圓周長:' + circle.circumference(14));           
//export default 指令
            //友善加載,import指令可以為該匿名函數指定任意名字。
            // export-default.js
            export default function () {
                console.log('foo');
            }
            // import-default.js
            import customer from './export-default';
            customer(); // 'foo'
--------------------------------------------------------------------------------------------
            //對應的import語句不需要使用大括号
            import customName from './index';
            customName(); // 'foo'
            //兩種寫法
            export default function () {
                console.log('foo');
            }
            //或者寫成
            function foo() {
                console.log('foo');
            }
            export default foo;
--------------------------------------------------------------------------------------------
            //export default 就是輸出一個叫做default的變量或方法
            // 正确
            export var a = 1;
            // 正确
            var a = 1;
            export default a;
            // 錯誤
            export default var a = 1;
            //export default指令輸出變量時,本質是将後面值,賦給default變量,是以可以直接将一個值寫在export default之後
            // 正确
            export default 42;
            // 報錯
            export 42;
--------------------------------------------------------------------------------------------
            //export default 允許用 as 任意命名,重命名為 default 有效
            function add(x, y) {
                return x * y;
            }
            export {add as default};
            // 等同于
            export default add;
            //main.js 引用
            import { default as add } from './index';
            //等同于
            import add from './index';
--------------------------------------------------------------------------------------------
            //有了export default指令,import 可以同時輸入預設方法和其他接口
            //moudle.js
            export default function (obj) {
                
            }
            export function each(obj, iterator, context) {
                
            }
            export { each as forEach };
            //index.js
            import a, { each, forEach } form 'moudle';
--------------------------------------------------------------------------------------------
            //export default也可以用來輸出類
            // MyClass.js
            export default class {
                
            }
            // main.js
            import MyClass from 'MyClass';
            let o = new MyClass();           
//import 和 export 複合寫法
            //export和import語句可以結合寫成一行。相當于對外轉發了接口,導緻目前子產品不能直接使用foo和bar。
            export { foo, bar } from 'my_module';
            // 可以簡單了解為
            import { foo, bar } from 'my_module';
            export { foo, bar };
--------------------------------------------------------------------------------------------
            //子產品的接口改名和整體輸出,也可以采用這種寫法。
            // 接口改名
            export { foo as myFoo } from 'my_module';
            // 整體輸出
            export * from 'my_module';
--------------------------------------------------------------------------------------------
            //預設接口的寫法如下。
            export { default } from 'foo';
--------------------------------------------------------------------------------------------
            //具名接口改為預設接口的寫法如下。
            export { es6 as default } from './someModule';
            // 等同于
            import { es6 } from './someModule';
            export default es6;
--------------------------------------------------------------------------------------------
            //預設接口也可以改名為具名接口。
            export { default as es6 } from './someModule';
--------------------------------------------------------------------------------------------
            //注意下面三種import語句,沒有對應的複合寫法。為了做到形式的對稱,現在有提案。
            import * as someIdentifier from "someModule";//*号重命名整體加載
            import someIdentifier from "someModule";//預設接口重命名
            import someIdentifier, { namedIdentifier } from "someModule";//同時輸入預設方法和其他接口           
//子產品繼承
            //circleplus子產品 繼承 circle子產品。
            // circle.js
            export function area(radius) {
              return Math.PI * radius * radius;
            }
            export function circumference(radius) {
              return 2 * Math.PI * radius;
            }
            export default function(){
                
            }
            // circleplus.js
            //這裡是複合寫法,export *,表示再輸出circle子產品所有屬性和方法。注意,export *指令會忽略circle子產品的default方法。然後,上面代碼又輸出了自定義的e變量和預設方法。
            export * from 'circle';
            export var e = 2.71828182846;
            export default function(x) {
              return Math.exp(x);
            }
            //也可以将circle的屬性或方法,改名後再輸出。将其改名為circleArea。
            // circleplus.js
            export { area as circleArea } from 'circle';
            //加載子產品 import exp表示,将circleplus子產品的預設方法加載為exp方法。
            // main.js
            import * as math from 'circleplus';
            import exp from 'circleplus';
            console.log(exp(math.e));           
//跨子產品常量
            //const聲明的常量隻在目前代碼塊有效。建一個專門的constants目錄,将各種常量寫在不同的檔案裡面,儲存在該目錄下。
            // constants/db.js
            export const db = {
              url: 'http://my.couchdbserver.local:5984',
              admin_username: 'admin',
              admin_password: 'admin password'
            };
            // constants/user.js
            export const users = ['root', 'admin', 'staff', 'ceo', 'chief', 'moderator'];
            //将這些檔案輸出的常量,合并在index.js裡面。
            // constants/index.js
            export {db} from './db';
            export {users} from './users';
            //使用的時候,直接加載index.js就可以了。
            // script.js
            import {db, users} from './constants/index';           

上面的總結,更加清晰明了,細節上還有很多地方需要注意,建議多敲代碼,明天再更、、、

繼續閱讀