在Javascript ES6標準中,我們可以用Arrow function來幫助我們解決bind的問題,但由於user的browser不一定support ES6,我們需要用Babel來向下兼容。
以下會詳述有關.bind()
、Arrow function和Babel的原理。
為甚麼要使用arrow function
在之前一篇文章,我們談到this在各種情況下會指不同的object。在ES6的class裡,經常需要用到this來指定class自身,但這並不是件容易的事,因為this會取決於執行時的環境而定。
一般我們需要在constructor裡bind this來確保得到正確的this:
class Example {
constructor() {
this.something = "Hello World";
this.printSomething = this.printSomething.bind(this);
}
printSomething() {
console.log(this.something);
}
}
當你有十個function,就需要bind十次。很麻煩是吧。
但使用了ES6的arrow function,class fucntion裡面的this必然會是class自身:
class Example {
something = "Hello World"
printSomething = () => {
console.log(this.something);
}
}
向下兼容問題
Arrow function是ES6的其中一個feature,而ES6算是比較新的語法,所以未必所有瀏覽器都支援新語法。
為了讓更多使用者能用到我們的Application,我們可以用Babel來轉譯ES6語法成為ES5甚至以前的語法。
Babel transform
Babel是一個JS編譯器,主要用途就是把一些用新語法(例如ES6)寫成的JS編譯成兼容的舊語法,讓未更新的browser都可以執行。
以下是Babel對arrow function所做的轉譯。
ES6
class Test {
world = 1
hello = () => {
console.log(this.world);
}
}
轉譯後
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Test = function Test() {
var _this = this;
_classCallCheck(this, Test);
this.world = 1;
this.hello = function () {
console.log(_this.world);
};
};
大家也可以到官方online compiler自己試一下。
我們可以看出主要有幾個重點:
- Class會變成function
- 這個function會define所有class properties(就像constructor一樣做法)
- Arrow function裡的
this
會變成local的_this
來確保正確reference
知道多一點Babel的背後運作,用起來就更得心應手了。
Appendix: .bind(this)
以下附上bind this的例子:
ES6
class Example {
constructor() {
this.something = "Hello World";
this.printSomething = this.printSomething.bind(this);
}
printSomething() {
console.log(this.something);
}
}
轉譯後
"use strict";
var _createClass = function () {...}();
function _classCallCheck(instance, Constructor) { ... }
var Example = function () {
function Example() {
_classCallCheck(this, Example);
this.something = "Hello World";
this.printSomething = this.printSomething.bind(this);
}
_createClass(Example, [{
key: "printSomething",
value: function printSomething() {
console.log(this.something);
}
}]);
return Example;
}();