前言
ECMAScript 6(以下簡稱ES6)是JavaScript語言的下一代標準。因爲當前版本的ES6是在2015年發佈的,所以又稱ECMAScript 2015。
Babel轉碼器
Babel
Babel是一個廣泛使用的ES6轉碼器,可以將ES6代碼轉爲ES5代碼,從而在現有環境執行。大家可以選擇自己習慣的工具來使用使用Babel,具體過程可直接在Babel官網查看:
let和const命令
基本用法
用來聲明變量,但是所有聲明的變量只在let命令所在的代碼塊中有效;
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
變量i是let聲明的,當前的i只在本輪循環有效,所以每一次循環的i其實都是一個新的變量,所以最後輸出的是6。
不存在變量提升
let命令改變了語法行爲,它所聲明的變量一定要在聲明後使用,否則報錯。
// let 的情況
console.log(error); // 報錯ReferenceError
let error = 2;
塊級作用域
function fun() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}
上面的函數有兩個代碼塊,都聲明瞭變量n,運行後輸出 5。這表示外層代碼塊不受內層代碼塊的影響。
不能重複聲明變量
let不允許在相同作用域內,重複聲明同一個變量。
function func() {
let a = 10;
let a = 1;
console.log(a); // 報錯
}
function func(a) {
let a; // 報錯
}
function func(a) {
{
let a; // 不報錯
}
}
const
const也用來聲明變量,但是聲明的是常量。一旦聲明,常量的值就不能改變。
const命令的常量 也是不提升,同樣存在暫時性死區,只在聲明所在的塊級作用域內有效.
const聲明的常量,也與let一樣不可重複聲明。
var message = "Hello!";
let age = 25;
const message = "Goodbye!";// 報錯
const age = 30;// 報錯
和let一樣不可重複聲明
if (true) {
const fun = 5;
}
fun // Uncaught ReferenceError: fun is not defined
塊級作用域
變量的解構賦值
ES6 允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱爲解構
let { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
----------------------
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
Symbol
ES6 引入了一種新的原始數據類型Symbol,表示獨一無二的值。
它是 JavaScript 語言的第七種數據類型,前六種是:undefined、null、布爾值(Boolean)、字符串(String)、數值(Number)、對象(Object)。
注意,Symbol函數前不能使用new命令,否則會報錯。這是因爲生成的Symbol是一個原始類型的值,不是對象
Symbol函數可以接受一個字符串作爲參數,表示對Symbol實例的描述,主要是爲了在控制檯顯示,或者轉爲字符串時,比較容易區分。
// 沒有參數的情況
var s1 = Symbol();
var s2 = Symbol();
s1 === s2 // false
// 有參數的情況
var s1 = Symbol("foo");
var s2 = Symbol("foo");
s1 === s2 // false
s1和s2都是Symbol函數的返回值,而且參數相同,但是它們是不相等的。
let sym = Symbol('My symbol');
"your symbol is " + sym
// TypeError: can't convert symbol to string
`your symbol is ${sym}`
// TypeError: can't convert symbol to string
Symbol 值不能與其他類型的值進行運算,會報錯
箭頭函數
ES6 允許使用“箭頭”(=>)定義函數,支持expression 和 statement 兩種形式。同時一點很重要的是它擁有詞法作用域的this值,幫你很好的解決this的指向問題,這是一個很酷的方式,可以幫你減少一些代碼的編寫。
注意
(1)函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象。
(2)不可以當作構造函數,也就是說,不可以使用new命令,否則會拋出一個錯誤。
(3)不可以使用arguments對象,該對象在函數體內不存在。如果要用,可以用 rest 參數代替。
(4)不可以使用yield命令,因此箭頭函數不能用作 Generator 函數。
function Timer() {
this.s1 = 0;
this.s2 = 0;
// 箭頭函數
setInterval(() => this.s1++, 1000);
// 普通函數
setInterval(function () {
this.s2++;
}, 1000);
}
var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1: 3
// s2: 0
Timer函數內部設置了兩個定時器,分別使用了箭頭函數和普通函數。前者的this綁定定義時所在的作用域(即Timer函數),後者的this指向運行時所在的作用域(即全局對象)。所以,3100 毫秒之後,timer.s1被更新了 3 次,而timer.s2一次都沒更新。
class Animal {
constructor(){
this.type = 'animal'
}
says(say){
setTimeout( () => {
console.log(this.type + ' says ' + say)
}, 1000)
}
}
var animal = new Animal()
animal.says('hi') //animal says hi
當我們使用箭頭函數時,函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象。
並不是因爲箭頭函數內部有綁定this的機制,實際原因是箭頭函數根本沒有自己的this,它的this是繼承外面的,因此內部的this就是外層代碼塊的this。
Module語法
在 ES6 之前,社區制定了一些模塊加載方案,最主要的有 CommonJS 和 AMD 兩種。前者用於服務器,後者用於瀏覽器。ES6 在語言標準的層面上,實現了模塊功能,而且實現得相當簡單,完全可以取代 CommonJS 和 AMD 規範,成爲瀏覽器和服務器通用的模塊解決方案。
ES6 模塊的設計思想,是儘量的靜態化,使得編譯時就能確定模塊的依賴關係,以及輸入和輸出的變量。CommonJS 和 AMD 模塊,都只能在運行時確定這些東西。比如,CommonJS 模塊就是對象,輸入時必須查找對象屬性。
export
ES6將一個文件視爲一個模塊,上面的模塊通過 export 向外輸出了一個變量。一個模塊也可以同時往外面輸出多個變量。
// profile.js
//寫法一:
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
//寫法二:
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
export {firstName, lastName, year};
import命令
定義好模塊的輸出以後就可以在另外一個模塊通過import引用。
//index.js
import {name, age} from './profile.js'
default
不用關係模塊輸出了什麼,通過 export default 指令就能加載到默認模塊,不需要通過 花括號來指定輸出的模塊,一個模塊只能使用 export default 一次
// default 導出
export default class { ... }
// 導入的時候不需要花括號
import test from './test.js';