嚴格模式
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
)
其中,尤其需要注意this
的限制。ES6 模組之中,頂層的this
指向undefined
,即不應該在頂層程式碼使用this
。
export 命令
模組功能主要由兩個命令構成:export
和import
。export
命令用於規定模組的對外介面,import
命令用於輸入其他模組提供的功能。
一個模組就是一個獨立的檔案。該檔案內部的所有變數,外部無法獲取。如果你希望外部能夠讀取模組內部的某個變數,就必須使用export
關鍵字輸出該變數。
export寫法一
下面是一個 JS 檔案,裡面使用export
命令輸出變數。
// profile.js
export var a = "1"
export var b = 2
export var c = ['hello', 'world']
上面程式碼是profile.js
檔案,儲存了資訊。ES6 將其視為一個模組,裡面用export
命令對外部輸出了三個變數。
export寫法二
export
的寫法,除了像上面這樣,還有另外一種。
var a = "1";
var b = 2;
var c = ['hello', 'world']
export {a, b, c};
上面程式碼在export
命令後面,使用大括號指定所要輸出的一組變數。它與前一種寫法(直接放置在var
語句前)是等價的,但是應該優先考慮
使用這種寫法。因為這樣就可以在指令碼尾部,一眼看清楚輸出了哪些變數。
export輸出函式或類
export
命令除了輸出變數,還可以輸出函式或類(class
)。
export function multiply(x, y) {
return x * y;
}
上面程式碼對外輸出一個函式multiply
。
export重新命名
通常情況下,export
輸出的變數就是本來的名字,但是可以使用as
關鍵字重新命名。
function v1() { ... }
function v2() { ... }
export {
v1 as streamV1,
v2 as streamV2,
v2 as streamLatestVersion
};
上面程式碼使用as
關鍵字,重新命名了函式v1
和v2
的對外介面。重新命名後,v2
可以用不同的名字輸出兩次。
import命令
使用export
命令定義了模組的對外介面以後,其他 JS
檔案就可以通過import
命令載入這個模組。
// main.js
import {a} from "./profile";
function test(){
console.log(a)
}
上面程式碼的import
命令,用於載入profile.js
檔案,並從中輸入變數。import
命令接受一對大括號,裡面指定要從其他模組匯入的變數名。大括號裡面的變數名,必須與被匯入模組(profile.js)
對外介面的名稱相同。
變數重新命名
如果想為輸入的變數重新取一個名字,import
命令要使用as
關鍵字,將輸入的變數重新命名。
import { a as newName } from './profile.js';
變數只讀
import
命令輸入的變數都是隻讀的,因為它的本質是輸入介面。也就是說,不允許在載入模組的指令碼里面,改寫介面。
import {a} from './xxx.js'
a = {}; // Syntax Error : 'a' is read-only;
上面程式碼中,指令碼載入了變數a
,對其重新賦值就會報錯,因為a
是一個只讀的介面。但是,如果a
是一個物件,改寫a
的屬性是允許的。
import {a} from './xxx.js'
a.foo = 'hello'; // 合法操作
上面程式碼中,a
的屬性可以成功改寫,並且其他模組也可以讀到改寫後的值。不過,這種寫法很難查錯,建議凡是輸入的變數,都當作完全只讀,不要輕易改變它的屬性。
import匯入路徑
import
後面的from
指定模組檔案的位置,可以是相對路徑,也可以是絕對路徑。如果不帶有路徑,只是一個模組名,那麼必須有配置檔案,告訴 JavaScript
引擎該模組的位置。
import { myMethod } from 'util';
上面程式碼中,util
是模組檔名,由於不帶有路徑,必須通過配置,告訴引擎怎麼取到這個模組。
import提升效果
注意,import
命令具有提升效果,會提升到整個模組的頭部,首先執行。
foo();
import { foo } from 'my_module';
上面的程式碼不會報錯,因為import
的執行早於foo
的呼叫。這種行為的本質是,import
命令是編譯階段執行的,在程式碼執行之前。