ECMAScript 6 簡介
ECMAScript 和 JavaScript 的關系:前者是后者的規格,后者是前者的一種實現,常場合,這兩個詞是可以互換的。
ECMAScript 6(以下簡稱 ES6)是 JavaScript 語言的標準,在 2015 年 6 月發布。它的目標,是使得 JavaScript 語言可以用來編寫復雜的大型應用程序,成為企業級開發語言。
版本 | 官方名稱 | 發布日期 |
---|---|---|
ES1 | ECMAScript 1 | 1997 |
ES2 | ECMAScript 2 | 1998 |
ES3 | ECMAScript 3 | 1999 |
ES4 | ECMAScript 4 | 從未發布過 |
ES5 | ECMAScript 5 | 2009 |
ES5.1 | ECMAScript 5.1 | 2011 |
ES6 | ECMAScript 2015(ECMAScript 6) | 2015 |
ES7 | ECMAScript 2016 | 2016 |
ES8 | ECMAScript 2017 | 2017 |
... | ... | ... |
因此,ES6 既是一個歷史名詞,也是一個泛指,含義是 5.1 版以后的 JavaScript 的下一代標準,涵蓋了 ES2015、ES2016、ES2017 等等
語法提案的批準流程
任何人都可以向標準委員會(又稱 TC39 委員會)提案,要求修改語言標準。
一種新的語法從提案到變成正式標準,需要經歷五個階段。每個階段的變動都需要由 TC39 委員會批準:
- Stage 0 - Strawman(展示階段)
- Stage 1 - Proposal(征求意見階段)
- Stage 2 - Draft(草案階段)
- Stage 3 - Candidate(候選人階段)
- Stage 4 - Finished(定案階段)
一個提案只要能進入 Stage 2,就差不多肯定會包括在以后的正式標準里面。ECMAScript 當前的所有提案,可以在 TC39 的官方網站GitHub.com/tc39/ecma262查看。
Nodejs環境安裝
Node.js 是一個基于 ?Chrome V8 JavaScript 引擎? 的 ?開源、跨平臺的 JavaScript 運行時環境,用于在服務器端運行 JavaScript 代碼。它讓開發者能夠使用 JavaScript 編寫后端服務(如 Web 服務器、API、數據庫交互等),從而統一前后端語言,提高開發效率。
?核心特性?
?非阻塞 I/O(異步編程)??
- 通過事件驅動和回調機制處理高并發請求,避免線程阻塞(例如:數據庫查詢時不會阻塞其他請求)。
- 適合 I/O 密集型應用(如實時聊天、文件操作)。
?單線程 + 事件循環?
- 主線程是單線程的,但通過事件循環(Event Loop)和異步任務(如?
setTimeout
、Promise
)實現高效并發。- 注意:CPU 密集型任務(如復雜計算)可能阻塞主線程,需用子進程(
worker_threads
?或?child_process
)拆分。?跨平臺?
- 支持 Windows、Linux、macOS 等系統。
?npm 生態?
- 內置包管理器 npm(Node Package Manager),擁有全球最大的開源庫生態系統(如 Express、Socket.IO 等)。
核心模塊?? ?Node.js 內置了常用模塊,無需額外安裝:
http
?/?https
:創建 HTTP 服務器或客戶端。fs
:文件系統操作(讀寫文件)。path
:處理文件路徑。events
:自定義事件監聽與觸發。stream
:處理數據流(如大文件分塊讀寫)。
Node.js官網:https://nodejs.org/en/?
安裝Node.js
在安裝Nodejs
的同時,會附帶一個npm
命令,npm
?是Node的包管理工具,這樣正是接下來我們要用到的。npm 的簡單結構有助于 Node.js 生態系統的激增,現在 npm 倉庫托管了超過 1,000,000 個可以自由使用的開源庫包。
npm
鏡像 由于服務器在國外,所以下載速度比較慢,我們可以用國內的鏡像
阿里云鏡像地址:https://npmmirror.com/
在命令行運行如下命令即可:
npm install -g cnpm --registry=https://registry.npmmirror.com
看到如下信息,代表安裝成功.
Babel轉碼器?
Babel 是一個廣泛使用的 ES6 轉碼器,可以將 ES6 代碼轉為 ES5 代碼,從而在老版本的瀏覽器執行。這意味著,你可以用 ES6 的方式編寫程序,又不用擔心現有環境是否支持.
瀏覽器支持性查看:https://caniuse.com/
Babel官網:https://babeljs.io/
轉碼示例:原始代碼用了箭頭函數,Babel 將其轉為普通函數,就能在不支持箭頭函數的 JavaScript 環境執行了。
// 轉碼前
input.map(item => item + 1);
// 轉碼后
input.map(function (item) {return item + 1;
});
Babel安裝流程
第一步:安裝 Babel
npm install --save-dev @babel/core
第二步:配置文件.babelrc
Babel 的配置文件是.babelrc,存放在項目的根目錄下。使用 Babel 的第一步,就是配置這個文件。該文件用來設置轉碼規則和插件,基本格式如下
{"presets": [],"plugins": []
}
第三步:轉碼規則
presets字段設定轉碼規則,官方提供以下的規則集,你可以根據需要安裝.
npm install --save-dev @babel/preset-env
第四步:將規則加入.babelrc
{"presets": ["@babel/env"],"plugins": []
}
Babel命令行轉碼
Babel 提供命令行工具@babel/cli
,用于命令行轉碼
npm install --save-dev @babel/cli
基本用法如下:
# 轉碼結果輸出到標準輸出
$ npx babel example.js# 轉碼結果寫入一個文件
# --out-file 或 -o 參數指定輸出文件
$ npx babel example.js --out-file compiled.js
# 或者
$ npx babel example.js -o compiled.js# 整個目錄轉碼
# --out-dir 或 -d 參數指定輸出目錄
$ npx babel src --out-dir lib
# 或者
$ npx babel src -d lib
ES6新命令
Let 命令
ES6
新增了let
命令,用來聲明變量。它的用法類似于var
,但是所聲明的變量,只在let
命令所在的代碼塊內有效。
let塊級作用域
{let a = 10;var b = 1;
}a // ReferenceError: a is not defined.
b // 1
for
循環的計數器,就很合適使用let
命令
for (let i = 0; i < 10; i++) {// ...
}
console.log(i);
// ReferenceError: i is not defined
對比var
和let
在循環中的應用
// var在for中的使用var a = [];
for (var i = 0; i < 10; i++) {a[i] = function () {console.log(i);};
}
a[6](); // 10// let在for中的使用
var a = [];
for (let i = 0; i < 10; i++) {a[i] = function () {console.log(i);};
}
a[6](); // 6
let不存在變量提升
var
命令會發生“變量提升”現象,即變量可以在聲明之前使用,值為undefined
。這種現象多多少少是有些奇怪的,按照一般的邏輯,變量應該在聲明語句之后才可以使用。
為了糾正這種現象,let
命令改變了語法行為,它所聲明的變量一定要在聲明后使用,否則報錯。
// var 的情況
console.log(foo); // 輸出undefined
var foo = 2;
// let 的情況
console.log(bar); // 報錯ReferenceError
let bar = 2;
let不允許重復聲明?let
不允許在相同作用域內,重復聲明同一個變量。
// 報錯
function func() {let a = 10;var a = 1;
}
// 報錯
function func() {let a = 10;let a = 1;
}
Const 命令
const
聲明一個只讀的常量。一旦聲明,常量的值就不能改變。
const PI = 3.1415;
PI // 3.1415PI = 3;
// TypeError: Assignment to constant variable.// const聲明的常量,也與let一樣不可重復聲明
var message = "Hello!";
let age = 25;// 以下兩行都會報錯
const message = "Goodbye!";
const age = 30;
const
聲明的變量不得改變值,這意味著,const
一旦聲明變量,就必須立即初始化,不能留到以后賦值.
const foo;
// SyntaxError: Missing initializer in const declaration
const
的作用域與let命令相同:只在聲明所在的塊級作用域內有效
if (true) {const MAX = 5;
}MAX // Uncaught ReferenceError: MAX is not defined
const
命令聲明的常量也是不存在提升
if (true) {console.log(MAX); // ReferenceErrorconst MAX = 5;
}
對象解構賦值?
解構可以用于對象,例如:
let {name,age} = {name:"iwen",age:20};
注意:對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值
let {age,name} = {name:"iwen",age:20}; age // 20let {sex,age,name} = {name:"iwen",age:20}; sex // undefined
?對象的解構賦值,可以很方便地將現有對象的方法,賦值到某個變量。
let { random,floor } = Math;
let { log } = console;
注意事項,如果要將一個已經聲明的變量用于解構賦值,必須非常小心。
let hello = "Hello";
let { hello } = {hello:"hello"}; // 報錯let hello = "Hello";
({ hello } = {hello:"hello"}); // 正確
字符串擴展
字符串Unicode 表示法:ES6 加強了對 Unicode 的支持,允許采用\uxxxx
形式表示一個字符,其中xxxx
表示字符的 Unicode 碼點。
Unicode?統一碼(Unicode),也叫萬國碼、單一碼,是計算機科學領域里的一項業界標準,包括字符集、編碼方案等。Unicode是為了解決傳統的字符編碼方案的局限而產生的,它為每種語言中的每個字符設定了統一并且唯一的二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。
"\u0061"
// "a"
字符串遍歷器接口?for...of
循環遍歷
for (let i of 'JavaScript') {console.log(i);
}
模板字符串? 是增強版的字符串,用反引號(`)標識。它可以當作普通字符串使用,也可以用來定義多行字符串,或者在字符串中嵌入變量。
let url = "www.baidu.com"
let h1 = "<a href='"+ url +"'>baidu</a>"
let h2 = `<a href='${url}'>baidu</a>`
字符串新增方法
傳統上,JavaScript 只有indexOf
方法,可以用來確定一個字符串是否包含在另一個字符串中。ES6 又提供了三種新方法。
- includes():返回布爾值,表示是否找到了參數字符串
- startsWith():返回布爾值,表示參數字符串是否在原字符串的頭部
- endsWith():返回布爾值,表示參數字符串是否在原字符串的尾部
let s = 'Hello world!';s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true
這三個方法都支持第二個參數,表示開始搜索的位置
let s = 'Hello world!';s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false
repeat
方法返回一個新字符串,表示將原字符串重復n
次。
'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""
ES2017 引入了字符串補全長度的功能。如果某個字符串不夠指定長度,會在頭部或尾部補全。padStart()
用于頭部補全,padEnd()
用于尾部補全。
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax''x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'
ES2019對字符串實例新增了trimStart()
和trimEnd()
這兩個方法。它們的行為與trim()
一致,trimStart()
消除字符串頭部的空格,trimEnd()
消除尾部的空格。它們返回的都是新字符串,不會修改原始字符串。
const s = ' JavaScript ';
s.trim() // "JavaScript"
s.trimStart() // "JavaScript "
s.trimEnd() // " JavaScript"
at()
方法接受一個整數作為參數,返回參數指定位置的字符,支持負索引(即倒數的位置)。
const str = 'hello';
str.at(1) // "e"
str.at(-1) // "o"
數組擴展
擴展運算符
擴展運算符(spread)是三個點(...
)。將一個數組轉為用逗號分隔的參數序列
console.log(...[1, 2, 3])
// 1 2 3
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
替代函數的 apply 方法 由于擴展運算符可以展開數組,所以不再需要apply
方法,將數組轉為函數的參數了.
// ES5 的寫法
Math.max.apply(null, [14, 3, 77])
// ES6 的寫法
Math.max(...[14, 3, 77])
// 等同于
Math.max(14, 3, 77);
合并數組 擴展運算符提供了數組合并的新寫法.
const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];
// ES5 的合并數組
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]
// ES6 的合并數組
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
新增方法
Array.from
方法用于將類數組轉為真正的數組
常見的類數組有三類:
- arguments
- 元素集合
- 類似數組的對象
arguments
function add(){let collect = Array.from(arguments);collect.push(40);console.log(collect);
}
add(10,20,30)
元素集合
let divs = document.querySelectorAll('div');
console.log(Array.from(divs));
類似數組的對象
let arrayLike = {'0': 'a','1': 'b','2': 'c',length: 3
};
let arr = Array.from(arrayLike);
console.log(arr);
Array.of()
方法用于將一組值,轉換為數組.
Array.of(3, 11, 8) // [3,11,8]
對象的擴展
ES6 允許在大括號里面,直接寫入變量和函數,作為對象的屬性和方法。這樣的書寫更加簡潔。
let name = "iwen"
const user = {name,age:20
}
?除了屬性簡寫,方法也可以簡寫.
const o = {method() {return "Hello!";}
};
// 等同于
const o = {method: function() {return "Hello!";}
};
這種寫法用于函數的返回值,將會非常方便
function getPoint() {const x = 1;const y = 10;return {x, y};
}
getPoint() // {x:1, y:10}
屬性名表達式?ES6 允許字面量定義對象時,用表達式作為對象的屬性名,即把表達式放在方括號內
let propKey = 'java';
let obj = {[propKey]: true,['a' + 'bc']: 123
};
對象的擴展運算符 ES2018 將這個運算符引入了對象
let z = { a: 3, b: 4 };
let n = { ...z };
console.log(n);
{...{}, a: 1}
// { a: 1 }
函數的擴展
ES6 允許使用“箭頭”(=>
)”定義函數
var add = (x) => x;
// 等同于
var add = function (x) {return x;
};
如果箭頭函數不需要參數或需要多個參數,就使用一個圓括號代表參數部分
var add = (x,y) => x+y;
// 等同于
var add = function (x,y) {return x+y;
};
var add = () => 100;
// 等同于
var add = function () {return 100;
};
如果箭頭函數的代碼塊部分多于一條語句,就要使用大括號將它們括起來,并且使用return
語句返回
var add = (x,y) => {var z = 10;return x+y+z
};
// 等同于
var add = function (x,y) {var z = 100return x+y+z
};
由于大括號被解釋為代碼塊,所以如果箭頭函數直接返回一個對象,必須在對象外面加上括號,否則會報錯。
var add = (x,y) => ({x:10,y:20});
箭頭函數的一個用處是簡化回調函數(匿名函數)
var arr = [10,20,30]
arr.map(item =>{console.log(item);
})
使用注意點?對于普通函數來說,內部的this
指向函數運行時所在的對象,但是這一點對箭頭函數不成立。它沒有自己的this
對象,內部的this
就是定義時上層作用域中的this
var name = "JavaScript"
var user = {name:"iwen",getName(){setTimeout(() =>{console.log(this.name); // iwen})}
}
user.getName()
注意:箭頭函數里面根本沒有自己的
this
,而是引用外層的this
Set 數據結構?
ES6 提供了新的數據結構 Set。它類似于數組,但是成員的值都是唯一的,沒有重復的值。
Set
本身是一個構造函數,用來生成 Set 數據結構。
const s = new Set();
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));
for (let i of s) {console.log(i);
}
// 2 3 5 4
通過add()
方法向 Set 結構加入成員,結果表明 Set 結構不會添加重復的值。
Set
函數可以接受一個數組作為參數
const set = new Set([1, 2, 3, 4, 4]);
[...set]
// [1, 2, 3, 4]
數組去除重復成員的方法
// 去除數組的重復成員
[...new Set(array)]
字符串去除重復字符
[...new Set('ababbc')].join('')
// "abc"
向 Set 加入值的時候,不會發生類型轉換,所以5
和"5"
是兩個不同的值。
var mySet = new Set();
mySet.add("5")
mySet.add(5)
console.log(mySet); // Set(2){'5', 5}
size屬性 返回Set
實例的成員總數
const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
items.size // 5
Set 數據結構方法
add() 添加方法
var mySet = new Set();
mySet.add("5")
console.log(mySet);
delete() 刪除某個值,返回一個布爾值,表示刪除是否
var mySet = new Set();
mySet.add("5")
var flag = mySet.delete("5");
console.log(flag); // true
has() 返回一個布爾值,表示該值是否為Set
的成員
var mySet = new Set();
mySet.add("5")
var flag = mySet.has("5");
console.log(flag); // true
clear() 清除所有成員,沒有返回值
var mySet = new Set();
mySet.add("5")
mySet.clear();
console.log(mySet); // Set(0){size: 0}
Promise 對象
Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。它由社區最早提出和實現,ES6 將其寫進了語言標準,統一了用法,原生提供了Promise
對象
所謂Promise
,簡單說就是一個容器,里面保存著某個未來才會結束的事件(通常是一個異步操作)的結果。從語法上說,Promise 是一個對象,從它可以獲取異步操作的消息。Promise 提供統一的 API,各種異步操作都可以用同樣的方法進行處理
有了Promise
對象,就可以將異步操作以同步操作的流程表達出來,避免了層層嵌套的回調函數。此外,Promise
對象提供統一的接口,使得控制異步操作更加容易
基本用法 ES6 規定,Promise
對象是一個構造函數,用來生成Promise
實例.
const promise = new Promise(function(resolve, reject) {// ... some codeif (/* 異步操作成功 */){resolve(value);} else {reject(error);}
});
Promise
構造函數接受一個函數作為參數,該函數的兩個參數分別是resolve
和reject
。它們是兩個函數,由 JavaScript 引擎提供,不用自己部署。Promise
實例生成以后,可以用then
方法分別指定resolved
狀態和rejected
狀態的回調函數。
promise.then(function(value) {// success
}, function(error) {// failure
});
?加載圖片資源例子:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div></div><script>function loadImageAsync(url) {var promise = new Promise(function (resolve, reject) {const image = new Image();image.onload = function () {resolve(image);};image.onerror = function () {reject(new Error('Could not load image at ' + url));};image.src = url;});return promise;}loadImageAsync("http://iwenwiki.com/api/vue-data/vue-data-1.png").then(function(data){console.log(data);$("div").append(data)},function(error){$("div").html(error)})</script>
</body>
</html>
Ajax實操示例:Promise封裝Ajax,讓網絡請求的異步操作變得更簡單
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>const getJSON = function (url) {const promise = new Promise(function (resolve, reject) {const handler = function () {if (this.readyState !== 4) {return;}if (this.status === 200) {resolve(this.response);} else {reject(new Error(this.statusText));}};const client = new XMLHttpRequest();client.open("GET", url);client.onreadystatechange = handler;client.responseType = "json";client.setRequestHeader("Accept", "application/json");client.send();});return promise;};getJSON("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php").then(function (json) {console.log(json);}, function (error) {console.error('出錯了', error);});</script>
</body>
</html>
Async 函數:async函數可以將異步操作變為同步操作
例子:
function print(){setTimeout(() =>{console.log("定時器");},1000)console.log("Hello");
}
print()
基本語法
function timeout(ms) {return new Promise((resolve) => {setTimeout(resolve, ms);});
}
async function asyncPrint(value, ms) {await timeout(ms);console.log(value);
}
asyncPrint('hello world', 50);
異步應用?
function ajax(url){return new Promise(function(resolve,reject){$.getJSON(url,function(result){resolve(result)},function(error){reject(error) })})
}
async function getInfo(){let ids = await ajax("http://iwenwiki.com/api/generator/list.php")let names = await ajax("http://iwenwiki.com/api/generator/id.php?id="+ids[0])let infos = await ajax("http://iwenwiki.com/api/generator/name.php?name=" + names.name)console.log(infos);
}
getInfo();
Class
JavaScript 語言中,生成實例對象的傳統方法是通過構造函數
function Point(x, y) {this.x = x;this.y = y;
}
Point.prototype.toString = function () {return '(' + this.x + ', ' + this.y + ')';
};
var p = new Point(1, 2);
ES6 提供了更接近傳統語言的寫法,引入了 Class(類)這個概念,作為對象的模板。通過class
關鍵字,可以定義類。基本上,ES6 的class
可以看作只是一個語法糖,它的絕大部分功能,ES5 都可以做到,新的class
寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已。
class Point {constructor(x, y) {this.x = x;this.y = y;}toString() {return '(' + this.x + ', ' + this.y + ')';}
}
constructor 方法
constructor()
方法是類的默認方法,通過new
命令生成對象實例時,自動調用該方法。一個類必須有constructor()
方法,如果沒有顯式定義,一個空的constructor()
方法會被默認添加。
class Point {
}
// 等同于
class Point {constructor() {}
}
生成類的實例的寫法,與 ES5 完全一樣,也是使用new
命令
class Point {// ...
}
// 報錯
var point = Point(2, 3);
// 正確
var point = new Point(2, 3);
類不存在變量提升(hoist),這一點與 ES5 完全不同
new Foo(); // ReferenceError
class Foo {}
Class屬性與方法
實例方法 通過類的實例對象調用方法
class People{say(){console.log("Hello");}
}
var p = new People();
p.say()
實例屬性 實例屬性指的是類的實例對象可調用的屬性
class People{constructor(name,age){this.name = name;this.age = age;}say(){console.log(this.name,this.age);}
}
var p = new People("iwen",20);
p.say()
console.log(p.name,p.age);
靜態方法 類相當于實例的原型,所有在類中定義的方法,都會被實例繼承。如果在一個方法前,加上static
關鍵字,就表示該方法不會被實例繼承,而是直接通過類來調用,這就稱為“靜態方法”
class Person {static classMethod() {console.log("Hello");}
}
Person.classMethod() // Hello
var p = new Person();
p.classMethod() // p.classMethod is not a function
?注意?如果靜態方法包含
this
關鍵字,這個this
指的是類,而不是實例。class People {static getSay() {this.say();}static say() {console.log('hello');}say() {console.log('world');} } People.getSay() // hello
靜態屬性 指的是 Class 本身的屬性,即Class.propName
class People{}
People.status = "等待"
console.log(People.status);
?Class 的繼承
Class 可以通過extends
關鍵字實現繼承,讓子類繼承父類的屬性和方法。extends 的寫法比 ES5 的原型鏈繼承,要清晰和方便很多
class Point {
}
class ColorPoint extends Point {
}
ES6 規定,子類必須在constructor()
方法中調用super()
,否則就會報錯,這是因為子類自己的this
對象,必須先通過父類的構造函數完成塑造,得到與父類同樣的實例屬性和方法,然后再對其進行加工,添加子類自己的實例屬性和方法。如果不調用super()
方法,子類就得不到自己的this
對象。
class Point {constructor(x,y){this.x = x;this.y = y;}getPoint(){console.log(this.x,this.y);}
}
class ColorPoint extends Point {constructor(x,y,z){super(x,y)this.z = z;}
}
let cp = new ColorPoint(10,20,30)
cp.getPoint();
Module 的語法
歷史上,JavaScript 一直沒有模塊(module)體系,無法將一個大程序拆分成互相依賴的小文件,再用簡單的方法拼裝起來。其他語言都有這項功能,比如 Ruby 的require
、Python 的import
,甚至就連 CSS 都有@import
,但是 JavaScript 任何這方面的支持都沒有,這對開發大型的、復雜的項目形成了巨大障礙
ES6 模塊是通過export
命令顯式指定輸出的代碼,再通過import
命令輸入。
export var Hello = "hello" // hello.js文件
import { Hello } from "./hello.js" // index.js文件
測試方式
我們采用Nodejs方式進行測試Module語法。但是nodejs采用的是CommonJS的模塊化規范,使用require引入模塊;而import是ES6的模塊化規范關鍵字。想要使用import,必須引入babel轉義支持,通過babel進行編譯,使其變成node的模塊化代碼。
第一步:全局安裝babel-cli?
npm install -g babel-cli
第二步:安裝 babel-preset-env?
npm install -D babel-preset-env
第三步:運行代碼?
babel-node --presets env index.js
export 命令?
// export命令導出變量
export var firstName = 'Java';
export var lastName = 'script';
export var year = 2000;// export命令導出函數
export function add(x, y) {return x + y;
};
import 命令
使用export
命令定義了模塊的對外接口以后,其他 JS 文件就可以通過import
命令加載這個模塊
// name.js
export var firstName = 'Java';
export var lastName = 'script';
export var year = 2000;
// main.js
import { firstName, lastName, year } from './profile.js';
如果想為輸入的變量重新取一個名字,import
命令要使用as
關鍵字,將輸入的變量重命名?
// value.js
export var value = 1;
// main.js
import { value as val } from './value.js';
除了指定加載某個輸出值,還可以使用整體加載,即用星號(*
)指定一個對象,所有輸出值都加載在這個對象上面?
// circle.js
export function area(radius) {return Math.PI * radius * radius;
}
export function circumference(radius) {return 2 * Math.PI * radius;
}// main.js
import { area, circumference } from './circle';
// 可以修改如下
import * as circle from './circle';
export default 命令
從前面的例子可以看出,使用import
命令的時候,用戶需要知道所要加載的變量名或函數名,否則無法加載。但是,用戶肯定希望快速上手,未必愿意閱讀文檔,去了解模塊有哪些屬性和方法
為了給用戶提供方便,讓他們不用閱讀文檔就能加載模塊,就要用到export default
命令,為模塊指定默認輸出。
// export-default.js
export default function () {console.log('foo');
}
其他模塊加載該模塊時,import
命令可以為該匿名函數指定任意名字?
// import-default.js
import customName from './export-default';
customName(); // 'foo'