ES6簡介
ECMAScript 6(以下簡稱ES6)是JavaScript語言的下一代標(biāo)準(zhǔn),于2015年6月批準(zhǔn)通過。ECMAScript6的目標(biāo)葵姥,是使得JavaScript語言可以用來編寫復(fù)雜的大型應(yīng)用程序紊浩,成為企業(yè)級(jí)開發(fā)語言。讓代碼更加準(zhǔn)確酌呆,更易于閱讀衡载。
ECMAScript是JavaScript語言的國際標(biāo)準(zhǔn),JavaScript是ECMAScript的實(shí)現(xiàn)(ES是規(guī)范肪笋,JS是實(shí)現(xiàn))月劈。在日常場(chǎng)合度迂,這兩個(gè)詞是可以互換的。
環(huán)境支持
目前還沒有任何一款瀏覽器支持ES6特性
Firefox 49支持93%猜揪;Chrome 52支持98%
Node.js對(duì)ES6的支持度比瀏覽器更高
ES6 to ES5轉(zhuǎn)換器
Traceur轉(zhuǎn)碼器
Traceur允許將ES6代碼直接插入網(wǎng)頁
(1)在網(wǎng)頁頭部加載Traceur庫文件
(2)script標(biāo)簽的type屬性的值是module惭墓,而不是text/javascript,編譯器會(huì)自動(dòng)將所有type=module的代碼編譯為ES5而姐,然后再交給瀏覽器執(zhí)行
<!DOCTYPE html>
<html>
<head>
<title>Hello, World!</title>
<script src="traceur.js"></script>
<script src="BrowserSystem.js"></script>
<script src="bootstrap.js"></script>
</head>
<body>
<script type="module">
class Greeter {
constructor(message) {
this.message = message;
}
greet() {
let element = document.querySelector('#message');
element.textContent = this.message;
}
}
let greeter = new Greeter('Hello World!');
greeter.greet();
</script>
<h1 id="message"></h1>
</body>
</html>
Babel轉(zhuǎn)碼器
Babel可以將ES6代碼轉(zhuǎn)為ES5代碼腊凶;得益于強(qiáng)大的Babel的存在,使我們可以方便的使用ES6的語法拴念,而不必考慮瀏覽器支持的問題钧萍。
// 轉(zhuǎn)碼前
input.map(item => item + 1);
// 轉(zhuǎn)碼后
input.map(function (item) {
return item + 1;
});
ES6特性
新語法
let和const
let聲明變量,只在let命令所在的代碼塊內(nèi)有效
為什么需要塊級(jí)作用域政鼠?
1风瘦、內(nèi)層變量可能會(huì)覆蓋外層變量
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = "hello world";
}
}
f(); // undefined
2、用來計(jì)數(shù)的循環(huán)變量泄露為全局變量
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5
const聲明常量公般,只在聲明所在的塊級(jí)作用域內(nèi)有效
const PI = 3.1415;
PI // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.
if (true) {
const MAX = 5;
}
MAX // Uncaught ReferenceError: MAX is not defined
嘗試去改變用 const 聲明的常量時(shí)万搔,就會(huì)報(bào)錯(cuò)
引用第三方庫的時(shí)聲明的變量,用 const 來聲明可以避免未來不小心重命名而導(dǎo)致出現(xiàn)bug
const monent = require('moment')
解構(gòu)賦值(Destructuring)
從數(shù)組和對(duì)象中提取值官帘,對(duì)變量進(jìn)行賦值瞬雹。本質(zhì)上,這種寫法屬于“模式匹配”刽虹,只要等號(hào)兩邊的模式相同酗捌,左邊的變量就會(huì)被賦予對(duì)應(yīng)的值。
var a = 1;
var b = 2;
var c = 3;
寫成
var [a, b, c] = [1, 2, 3];
//提取值
var jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]
//遍歷Map結(jié)構(gòu)
var map = new Map();
map.set('first', 'hello');
map.set('second', 'world');
for (let [key, value] of map) {
console.log(key + " is " + value);
}
// first is hello
// second is world
箭頭函數(shù)(Fat arrow functions)
允許使用 =>
定義函數(shù)涌哲,箭頭函數(shù)自動(dòng)綁定當(dāng)前上下文 this胖缤,更簡潔的語法和與父作用域共享關(guān)鍵字this
var f = v => v;
//等同于
var f = function(v) {
return v;
};
function getVerifiedToken(selector) {
return getUsers(selector)
.then(function (users) { return users[0]; })
.then(verifyUser)
.then(function (user, verifiedToken) { return verifiedToken; })
.catch(function (err) { log(err.stack); });
}
使用箭頭函數(shù)
function getVerifiedToken(selector) {
return getUsers(selector)
.then(users => users[0])
.then(verifyUser)
.then((user, verifiedToken) => verifiedToken)
.catch(err => log(err.stack));
}
function
和{}
都消失了,所有的回調(diào)函數(shù)都只出現(xiàn)在了一行里膛虫。當(dāng)只有一個(gè)參數(shù)時(shí)草姻,
()
也消失了(rest參數(shù)是一個(gè)例外,如(...args) => ...)稍刀。當(dāng)
{}
消失后撩独,return
關(guān)鍵字也跟著消失了。單行的箭頭函數(shù)會(huì)提供一個(gè)隱式的return账月。
胖箭頭函數(shù)不產(chǎn)生屬于它自己上下文的this
$('.current-time').each(function () {
var self = this;
setInterval(function () {
$(self).text(Date.now());
}, 1000);
});
$('.current-time').each(function () {
setInterval(() => $(this).text(Date.now()), 1000);
});
生成器(Generator)
Generator 是一種可以停止并在之后重新進(jìn)入的函數(shù)综膀。生成器的環(huán)境(綁定的變量)會(huì)在每次執(zhí)行后被保存,下次進(jìn)入時(shí)可繼續(xù)使用局齿。function關(guān)鍵字后面有個(gè)*
號(hào)剧劝,函數(shù)體內(nèi)可以使用yield
語句進(jìn)行流程控制。
function* gen() {
yield 'hello';
yield 'world';
return true;
}
var iter = gen();
iter.next()
// { value: 'hello', done: false }
iter.next()
// { value: 'world', done: false }
iter.next()
// { value: undefined, done: true }
使用for...of語句時(shí)不需要使用next方法
function* fibonacci() {
let [prev, curr] = [0, 1];
for (;;) {
[prev, curr] = [curr, prev + curr];
yield curr;
}
}
for (let n of fibonacci()) {
if (n > 1000) break;
console.log(n);
}
遍歷器(Iterator)
Iterator是一種接口抓歼,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的訪問機(jī)制讥此。任何數(shù)據(jù)結(jié)構(gòu)只要部署Iterator接口拢锹,就可以完成遍歷操作(即依次處理該數(shù)據(jù)結(jié)構(gòu)的所有成員)
是為各種數(shù)據(jù)結(jié)構(gòu),提供一個(gè)統(tǒng)一的萄喳、簡便的訪問接口卒稳;
是使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列;
Iterator接口主要供
for...of
使用
使用TypeScript的寫法他巨,遍歷器接口(Iterable)充坑、指針對(duì)象(Iterator)和next方法返回值的規(guī)格可以描述如下
interface Iterable {
[Symbol.iterator]() : Iterator,
}
interface Iterator {
next(value?: any) : IterationResult,
}
interface IterationResult {
value: any,
done: boolean,
}
修飾器(Decorator)
修飾器(Decorator)是一個(gè)函數(shù),用來修改類的行為染突。這是ES7的一個(gè)提案捻爷,目前Babel轉(zhuǎn)碼器已經(jīng)支持。修飾器對(duì)類的行為的改變份企,是代碼編譯時(shí)發(fā)生的也榄,而不是在運(yùn)行時(shí)
@decorator
class A {}
// 等同于
class A {}
A = decorator(A) || A;
其他特性
Symbol數(shù)據(jù)類型
Set和Map數(shù)據(jù)結(jié)構(gòu)
異步操作和Async函數(shù)
Proxy和Reflect
二進(jìn)制數(shù)組
Promise對(duì)象
標(biāo)準(zhǔn)庫擴(kuò)展
字符串的擴(kuò)展
函數(shù)的擴(kuò)展
數(shù)值的擴(kuò)展
數(shù)組的擴(kuò)展
對(duì)象的擴(kuò)展
字符串?dāng)U展-模板字符串
$('#result').append(
'There are <b>' + basket.count + '</b> ' +
'items in your basket, ' +
'<em>' + basket.onSale +
'</em> are on sale!'
);
$('#result').append(`
There are <b>${basket.count}</b> items
in your basket, <em>${basket.onSale}</em>
are on sale!
`);
函數(shù)擴(kuò)展-函數(shù)默認(rèn)值
在ES6之前,不能直接為函數(shù)的參數(shù)指定默認(rèn)值司志,只能采用變通的方法手蝎,ES6允許為函數(shù)的參數(shù)設(shè)置默認(rèn)值,即直接寫在參數(shù)定義的后面俐芯。
function log(x){
x = x || 'hello'
console.log(x)
}
log()
function log(x = 'hello'){
console.log(type)
}
log()
函數(shù)擴(kuò)展-rest參數(shù)
ES6引入rest參數(shù)(形式為“...變量名”),用于獲取函數(shù)的多余參數(shù)钉鸯。rest參數(shù)之后不能再有其他參數(shù)(即只能是最后一個(gè)參數(shù))吧史。
function add(...types){
console.log(types)
}
add('a', 'b', 'c') //["a", "b", "c"]
面向?qū)ο蠛湍K化
Class
JavaScript語言的傳統(tǒng)方法是通過構(gòu)造函數(shù),定義并生成新對(duì)象唠雕。寫法跟傳統(tǒng)的面向?qū)ο笳Z言差異很大贸营。
類的繼承,Class 之間可以通過extends關(guān)鍵字實(shí)現(xiàn)繼承岩睁,這比ES5的通過修改原型鏈實(shí)現(xiàn)繼承钞脂,要清晰和方便很多
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);
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y); // 調(diào)用父類的constructor(x, y)
this.color = color;
}
toString() {
return this.color + ' ' + super.toString(); // 調(diào)用父類的toString()
}
}
super關(guān)鍵字
(1)作為函數(shù)調(diào)用時(shí)(即super(...args)),super代表父類的構(gòu)造函數(shù)捕儒。
(2)作為對(duì)象調(diào)用時(shí)(即super.prop或super.method())冰啃,super代表父類
模塊化
import、export
語言層級(jí)支持刘莹,無需引入第三方庫阎毅,不再引用seajs和requirejs就能使用模塊
統(tǒng)一的API,使用保留關(guān)鍵字 import 和 export 点弯,從而在瀏覽器實(shí)現(xiàn)后能最大程度的向下兼容
精簡語法扇调、唯一導(dǎo)出出口(single exports)和循環(huán)依賴(cyclic dependencies)的特點(diǎn)
支持結(jié)構(gòu)的靜態(tài)分析(靜態(tài)檢查,優(yōu)化等等)
// a.js如下
import {bar} from './b.js';
console.log('a.js');
console.log(bar);
export let foo = 'foo';
// b.js
import {foo} from './a.js';
console.log('b.js');
console.log(foo);
export let bar = 'bar';
babel-node a.js
//結(jié)果
b.js
undefined
a.js
bar
由于a.js的第一行是加載b.js抢肛,所以先執(zhí)行的是b.js狼钮。而b.js的第一行又是加載a.js碳柱,這時(shí)由于a.js已經(jīng)開始執(zhí)行了,所以不會(huì)重復(fù)執(zhí)行熬芜,而是繼續(xù)往下執(zhí)行b.js莲镣,所以第一行輸出的是b.js。
接著猛蔽,b.js要打印變量foo剥悟,這時(shí)a.js還沒執(zhí)行完,取不到foo的值曼库,導(dǎo)致打印出來是undefined区岗。b.js執(zhí)行完,開始執(zhí)行a.js毁枯,這時(shí)就一切正常了慈缔。
ES6應(yīng)用
組件框架轉(zhuǎn)向 ES6開發(fā)
angular2
react
Aurelia
...
總結(jié)
Let和Const更加準(zhǔn)確
解構(gòu)和箭頭函數(shù)更加精簡
標(biāo)準(zhǔn)庫擴(kuò)展
借鑒其他語言實(shí)現(xiàn)生成器、遍歷器等
Promise將最佳實(shí)踐標(biāo)準(zhǔn)化
Module / Class 等讓 JS 更適合大型編程