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';
上面的總結,更加清晰明了,細節上還有很多地方需要注意,建議多敲代碼,明天再更、、、