Learn ES2015的翻譯與筆記。
利用Babel的REPL可以很快測試看出ES5與ES6語法差異。
使用babel的CLI工具來測試
$ npm install --g babel
監看測試的檔案並且重新編譯:
$ babel script.js --watch -o script_compiled.js
或是直接使用io.js。注意,不是所有的ES6特性 iojs都實作好了, 請參考ECMAScript 6 compatibility table。
=>
箭頭函數表示式 (Arrow function expression,又叫 fat arrow function) 比起一般的函數表示式語法更短以及詞彙上綁定 this 變數,
所有的箭頭函數都是無名函數 (anonymous function).
ES6 code:
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);
相當於ES5 code:
var odds = evens.map(function (v) {
return v + 1;
});
var nums = evens.map(function (v, i) {
return v + i;
});
使用=>
讓程式看起來簡潔多了!
ES6 code:
var bob = {
_name: "Bob",
_friends: ['aaa','bbb','ccc'],
printFriends() {
this._friends.forEach(f =>
console.log(this._name + " knows " + f));
}
}
ES5函數的this變數在不同狀況下一直指向不同值, 現在箭頭函數會自動將 this 變數綁定到其定義時所在的物件。
ES5 code: (注意this
綁定到bob object)
var bob = {
_name: "Bob",
_friends: ['aaa', 'bbb', 'ccc'],
printFriends: function printFriends() {
var _this = this;
this._friends.forEach(function (f) {
return console.log(_this._name + " knows " + f);
});
}
};
Classes就是 prototype-bases OO語法的糖衣, 支援prototype-based inheritance, super calls, instances和 static methods, constructors:
class SkinnedMesh extends THREE.Mesh {
constructor(geometry, materials) {
super(geometry, materials);
this.idMatrix = SkinnedMesh.defaultMatrix();
this.bones = [];
this.boneMatrices = [];
//...
}
update(camera) {
//...
super.update();
}
static defaultMatrix() {
return new THREE.Matrix4();
}
}
有C++, Python, Java或是其他OO的概念, 更方便上手了。
Object literals被延伸用來在建立時期支援設定prototype:
var obj = {
// __proto__
__proto__: theProtoObj,
// Shorthand for ‘handler: handler’
handler,
// Methods
toString() {
// Super calls
return "d " + super.toString();
},
// Computed (dynamic) property names
[ 'prop_' + (() => 42)() ]: 42
};
Template strings提供一個建立string的語法糖。(很像Perl, Python)
多行字串, 注意是使用鍵盤左上角的back-tick符號, 而不是常見的單引號:
// Multiline strings
`In ES5 this is
not legal.`
相當於ES5的:
"In ES5 this is\n not legal.";
Template string:
// Interpolate variable bindings
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
相當於ES5的:
// Interpolate variable bindings
var name = "Bob", time = "today";
"Hello " + name + ", how are you " + time + "?";
var [a, ,b] = [1, 2, 3];
var {c,d} = {a:1, d:2};
var [e, f, ...g] = [1,2,3,4,5]; //ES7語法 babel也支援!
var [h = 1] = [];
console.log(a); // 1
console.log(b); // 2
console.log(c); // undefined
console.log(d); // 2
console.log(g); // [3,4,5]
console.log(h); // 1
有了Destructuring功能, 可以很方便的做到兩個變數值互換, 不再需要額外的temp變數了:
var a = 1;
var b = 3;
[a, b] = [b, a];
實現了 multi-values return功能, 從傳回的multi-values取我們想要的值:
function f(){
return [1, 2, 3];
}
var a, b;
[a, b, c]=f(); //a為1, b為2, c為3
var c = f();//c為[1,2]
var [d, ,e] = f(); //d為1, e為3
以前要寫一個帶有預設值參數的JS函式很搞剛, 例如我想寫個function, 有兩個參數x, y, 我像要y的預設參數值為12, 那在ES5會寫成這樣:
function f(x) {
var y = arguments[1] === undefined ? 12 : arguments[1];
return x + y;
}
f(3) == 15;
用ES6:
var f = (x, y=12) => x +y;
現在可以很方便的撰寫具有預設參數值的函式:
function drawES6Chart({
size = 'big',
cords = { x: 0, y: 0 },
radius = 25} = {})
{
console.log(size, cords, radius);
}
//輸出: big { x: 18, y: 30 } 30
drawES6Chart({
cords: { x: 18, y: 30 },
radius: 30
});
//輸出: big { x: 0, y: 0 } 25
drawES6Chart();
Rest:
var f= (x, ...y) => x * y.length;
f(3, "hello", true); //傳回6
Spread:
var f = (x, y, z) => x + y + z;
f(...[1,2,3]); //6
let
用來宣告block scope的變數,
const
就是 single-assignment, 避免重複賦值:
function f() {
{
let x;
{
// okay, block scoped name
const x = "sneaky";
// error, const不能重複賦值
x = "foo";
}
// error, 在同一個block裏面不能重複宣告
let x = "inner";
}
}
var
和let
的不同, 可以由以下來比較:
function foo() {
console.log( x ); //undefined
console.log( y ); //error
var x = 1;
if (x === 1) {
let y = 2;
}
console.log( y ); //error
}
foo();
console.log( x ); //error
第一個列印x得到的值為undefined, 因為變數x還沒有賦與值,
接下來列印兩個y會得到error, 因為我們用的是let
宣告y,為block scope,
y只存在if這個block裏面, 列印的y並沒有在這個block裏面, 因此會列印出錯誤。
最後一個列印x也會得到error, 因為我們用var
宣告x, 最後一個列印x已經超出function foo()的scope之外。
讓let
變成宣告為function scope也很簡單, 只要把let
宣告放在function內容的第1行就好了! 例如:
function foo( x ) {
let y;
if (x === 1) {
y = 2;
}
console.log( y );
}
foo( 1 ); //2
console.log( y ); //error
Destructuring assignment - MDN