- BabelJs 教程
- BabelJs - 首頁
- BabelJs - 概述
- BabelJs - 環境搭建
- BabelJs - 命令列介面 (CLI)
- BabelJs - ES6 程式碼執行
- BabelJs - 使用 Babel 6 進行專案設定
- BabelJs - 使用 Babel 7 進行專案設定
- 將 ES6 特性轉換為 ES5
- 將 ES6 模組轉換為 ES5
- 將 ES7 特性轉換為 ES5
- 將 ES8 特性轉換為 ES5
- BabelJs - Babel 外掛
- BabelJs - Babel Polyfill
- BabelJs - Babel 命令列介面 (CLI)
- BabelJs - Babel 預設
- Babel 與 Webpack 的結合使用
- Babel 與 JSX 的結合使用
- Babel 與 Flow 的結合使用
- BabelJS 與 Gulp 的結合使用
- BabelJs - 示例
- BabelJs 有用資源
- BabelJs - 快速指南
- BabelJs - 有用資源
- BabelJs - 討論
BabelJS - 將 ES6 特性轉換為 ES5
本章我們將瞭解 ES6 新增的功能特性。我們還將學習如何使用 BabelJS 將這些特性編譯成 ES5。
以下是本章將討論的各種 ES6 特性:
- Let + Const
- 箭頭函式
- 類
- Promise
- 生成器
- 解構
- 迭代器
- 模板字面量
- 增強型物件
- 預設引數、剩餘引數和擴充套件運算子
Let + Const
Let 聲明瞭一個 JavaScript 塊作用域區域性變數。請考慮以下示例以瞭解 let 的用法。
示例
let a = 1;
if (a == 1) {
let a = 2;
console.log(a);
}
console.log(a);
輸出
2 1
第一個控制檯輸出 2 的原因是a 使用let再次宣告,並且僅在if塊中可用。使用 let 宣告的任何變數都僅在其宣告的塊內可用。我們使用 let 兩次聲明瞭變數 a,但這不會覆蓋 a 的值。
這就是 var 和 let 關鍵字的區別。當您使用 var 宣告變數時,該變數將在函式的作用域內可用,如果宣告為全域性變數,則其行為將類似於全域性變數。
如果使用 let 宣告變數,則該變數在塊作用域內可用。如果在 if 語句內宣告,則它僅在 if 塊內可用。這同樣適用於 switch、for 迴圈等。
現在我們將瞭解使用 babeljs 進行 ES5 程式碼轉換。
讓我們執行以下命令來轉換程式碼:
npx babel let.js --out-file let_es5.js
let 關鍵字從 es6 到 es5 的輸出如下:
使用 ES6 的 Let
let a = 1;
if (a == 1) {
let a = 2;
console.log(a);
}
console.log(a);
使用 babel 轉換為 ES5
"use strict";
var a = 1;
if (a == 1) {
var _a = 2;
console.log(_a);
}
console.log(a);
如果您看到 ES5 程式碼,let 關鍵字將被var關鍵字替換。此外,if 塊內的變數被重新命名為_a,以獲得與使用let關鍵字宣告時相同的效果。
Const
在本節中,我們將學習 ES6 和 ES5 中 const 關鍵字的工作原理。const 關鍵字也在作用域內可用;如果在作用域外,則會丟擲錯誤。一旦賦值,const 宣告的變數的值就不能更改。讓我們考慮以下示例來了解 const 關鍵字的用法。
示例
let a =1;
if (a == 1) {
const age = 10;
}
console.log(age);
輸出
Uncaught ReferenceError: age is not defined at:5:13
上述輸出丟擲一個錯誤,因為 const age 在 if 塊內定義,並且在 if 塊內可用。
我們將瞭解使用 BabelJS 轉換為 ES5 的過程。
ES6
let a =1;
if (a == 1) {
const age = 10;
}
console.log(age);
命令
npx babel const.js --out-file const_es5.js
使用 BabelJS 轉換為 ES6
"use strict";
var a = 1;
if (a == 1) {
var _age = 10;
}
console.log(age);
在 ES5 中,const 關鍵字將被 var 關鍵字替換,如上所示。
箭頭函式
箭頭函式比變量表達式具有更短的語法。它也稱為胖箭頭函式或 lambda 函式。該函式沒有自己的 this 屬性。在此函式中,省略了關鍵字 function。
示例
var add = (x,y) => {
return x+y;
}
var k = add(3,6);
console.log(k);
輸出
9
使用 BabelJS,我們將把上述程式碼轉換為 ES5。
ES6 - 箭頭函式
var add = (x,y) => {
return x+y;
}
var k = add(3,6);
console.log(k);
命令
npx babel arrowfunction.js --out-file arrowfunction_es5.js
BabelJS - ES5
使用 Babel,箭頭函式將轉換為如下所示的變量表達式函式。
"use strict";
var add = function add(x, y) {
return x + y;
};
var k = add(3, 6);
console.log(k);
類
ES6 帶來了新的類特性。類類似於 ES5 中可用的基於原型的繼承。class 關鍵字用於定義類。類就像特殊的函式,並且與函式表示式具有相似之處。它有一個建構函式,它在類內部呼叫。
示例
class Person {
constructor(fname, lname, age, address) {
this.fname = fname;
this.lname = lname;
this.age = age;
this.address = address;
}
get fullname() {
return this.fname +"-"+this.lname;
}
}
var a = new Person("Siya", "Kapoor", "15", "Mumbai");
var persondet = a.fullname;
輸出
Siya-Kapoor
ES6 - 類
class Person {
constructor(fname, lname, age, address) {
this.fname = fname;
this.lname = lname;
this.age = age;
this.address = address;
}
get fullname() {
return this.fname +"-"+this.lname;
}
}
var a = new Person("Siya", "Kapoor", "15", "Mumbai");
var persondet = a.fullname;
命令
npx babel class.js --out-file class_es5.js
BabelJS - ES5
使用 babeljs 添加了額外的程式碼來確保類的功能與 ES5 中相同。BabelJs 確保功能與在 ES6 中一樣。
"use strict";
var _createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var Person = function () {
function Person(fname, lname, age, address) {
_classCallCheck(this, Person);
this.fname = fname;
this.lname = lname;
this.age = age;
this.address = address;
}
_createClass(Person, [{
key: "fullname",
get: function get() {
return this.fname + "-" + this.lname;
}
}]);
return Person;
}();
var a = new Person("Siya", "Kapoor", "15", "Mumbai");
var persondet = a.fullname;
Promise
JavaScript Promise 用於管理程式碼中的非同步請求。
它簡化了操作並使程式碼保持整潔,因為您可以管理來自具有依賴性的非同步請求的多個回撥。Promise 提供了一種更好的處理回撥函式的方法。Promise 是 ES6 的一部分。預設情況下,當您建立 Promise 時,Promise 的狀態為等待中。
Promise 有三種狀態:
- 等待中 (初始狀態)
- 已完成 (成功完成)
- 已拒絕 (失敗)
new Promise() 用於構造 Promise。Promise 建構函式帶有一個引數,該引數是一個回撥函式。回撥函式有兩個引數 - resolve 和 reject;
這兩個都是內部函式。您編寫的非同步程式碼,即 Ajax 呼叫、影像載入、計時函式將進入回撥函式。
如果回撥函式中執行的任務成功,則呼叫 resolve 函式;否則,將使用錯誤詳細資訊呼叫 reject 函式。
以下程式碼行顯示了一個 Promise 結構呼叫:
var _promise = new Promise (function(resolve, reject) {
var success = true;
if (success) {
resolve("success");
} else {
reject("failure");
}
});
_promise.then(function(value) {
//once function resolve gets called it comes over here with the value passed in resolve
console.log(value); //success
}).catch(function(value) {
//once function reject gets called it comes over here with the value passed in reject
console.log(value); // failure.
});
ES6 Promise 示例
let timingpromise = new Promise((resolve, reject) => {
setTimeout(function() {
resolve("Promise is resolved!");
}, 1000);
});
timingpromise.then((msg) => {
console.log(msg);
});
輸出
Promise is resolved!
ES6 - Promise
let timingpromise = new Promise((resolve, reject) => {
setTimeout(function() {
resolve("Promise is resolved!");
}, 1000);
});
timingpromise.then((msg) => {
console.log(msg);
});
命令
npx babel promise.js --out-file promise_es5.js
BabelJS - ES5
"use strict";
var timingpromise = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("Promise is resolved!");
}, 1000);
});
timingpromise.then(function (msg) {
console.log(msg);
});
對於 Promise,轉換後的程式碼沒有變化。我們需要使用 babel-polyfill 才能使其在舊版瀏覽器上執行。babel-polyfill 的詳細資訊在 babel-polyfill 章節中解釋。
生成器
生成器函式類似於普通的function。該函式具有特殊的語法 function*,其中 * 用於函式,以及yield關鍵字用於在函式內使用。這旨在根據需要暫停或啟動函式。一旦執行開始,普通的函式就不能在中途停止。它要麼執行整個函式,要麼在遇到 return 語句時停止。生成器在這裡的行為不同,您可以使用 yield 關鍵字暫停函式,並在需要時再次呼叫生成器來啟動它。
示例
function* generatorfunction(a) {
yield a;
yield a +1 ;
}
let g = generatorfunction(8);
console.log(g.next());
console.log(g.next());
輸出
{value: 8, done: false}
{value: 9, done: false}
ES6 - 生成器
function* generatorfunction(a) {
yield a;
yield a +1 ;
}
let g = generatorfunction(8);
console.log(g.next());
console.log(g.next());
命令
npx babel generator.js --out-file generator_es5.js
BabelJS - ES5
"use strict";
var _marked = /*#__PURE__*/regeneratorRuntime.mark(generatorfunction);
function generatorfunction(a) {
return regeneratorRuntime.wrap(function generatorfunction$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return a;
case 2:
_context.next = 4;
return a + 1;
case 4:
case "end":
return _context.stop();
}
}
}, _marked, this);
}
var g = generatorfunction(8);
console.log(g.next());
console.log(g.next());
迭代器
JavaScript 迭代器返回一個 JavaScript 物件,該物件具有值。該物件還有一個名為 done 的標誌,其值為 true/false。如果它不是迭代器的結尾,則返回 false。讓我們考慮一個示例,並檢視迭代器在陣列上的工作原理。
示例
let numbers = [4, 7, 3, 10]; let a = numbers[Symbol.iterator](); console.log(a.next()); console.log(a.next()); console.log(a.next()); console.log(a.next()); console.log(a.next());
在上面的示例中,我們使用了數字陣列,並使用Symbol.iterator作為索引在陣列上呼叫了一個函式。
使用 next() 在陣列上獲得的輸出如下:
{value: 4, done: false}
{value: 7, done: false}
{value: 3, done: false}
{value: 10, done: false}
{value: undefined, done: true}
輸出給出一個物件,其中 value 和 done 作為屬性。每次next()方法呼叫都從陣列中返回下一個值,done 為 false。只有當陣列中的元素完成時,done 的值才為 true。我們可以將其用於迭代陣列。還有更多可用的選項,例如for-of迴圈,使用方法如下:
示例
let numbers = [4, 7, 3, 10];
for (let n of numbers) {
console.log(n);
}
輸出
4 7 3 10
當for-of 迴圈使用鍵時,它會提供如上所示的陣列值的詳細資訊。我們將檢查這兩種組合,並檢視 babeljs 如何將其轉換為 es5。
示例
let numbers = [4, 7, 3, 10];
let a = numbers[Symbol.iterator]();
console.log(a.next());
console.log(a.next());
console.log(a.next());
console.log(a.next());
console.log(a.next());
let _array = [4, 7, 3, 10];
for (let n of _array) {
console.log(n);
}
命令
npx babel iterator.js --out-file iterator_es5.js
輸出
"use strict";
var numbers = [4, 7, 3, 10];
var a = numbers[Symbol.iterator]();
console.log(a.next());
console.log(a.next());
console.log(a.next());
console.log(a.next());
console.log(a.next());
var _array = [4, 7, 3, 10];
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = _array[Symbol.iterator](),
_step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
_iteratorNormalCompletion = true) {
var n = _step.value;
console.log(n);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
es5 中添加了for-of迴圈的更改。但是迭代器.next 保持不變。我們需要使用babel-polyfill才能使其在舊版瀏覽器中執行。Babel-polyfill 與 babel 一起安裝,並且可以從 node_modules 中使用,如下所示:
示例
<html>
<head>
<script type="text/javascript" src="node_modules/babel-polyfill/dist/polyfill.min.js"></script>
<script type="text/javascript" src="iterator_es5.js"></script>
</head>
<body>
<h1>Iterators</h1>
</body>
</html>
輸出
解構
解構屬性的行為類似於 JavaScript 表示式,它從陣列、物件中解包值。
以下示例將解釋解構語法的用法。
示例
let x, y, rem;
[x, y] = [10, 20];
console.log(x);
console.log(y);
[x, y, ...rem] = [10, 20, 30, 40, 50];
console.log(rem);
let z = 0;
({ x, y } = (z) ? { x: 10, y: 20 } : { x: 1, y: 2 });
console.log(x);
console.log(y);
輸出
10 20 [30, 40, 50] 1 2
以上程式碼行顯示瞭如何將陣列右側的值分配給左側的變數。帶有...rem的變數獲取陣列中所有剩餘的值。
我們還可以使用條件運算子將左側物件的值分配如下:
({ x, y } = (z) ? { x: 10, y: 20 } : { x: 1, y: 2 });
console.log(x); // 1
console.log(y); // 2
讓我們使用 babeljs 將其轉換為 ES5:
命令
npx babel destructm.js --out-file destruct_es5.js
destruct_es5.js
"use strict";
var x = void 0,
y = void 0,
rem = void 0;
x = 10;
y = 20;
console.log(x);
console.log(y);
x = 10;
y = 20;
rem = [30, 40, 50];
console.log(rem);
var z = 0;
var _ref = z ? { x: 10, y: 20 } : { x: 1, y: 2 };
x = _ref.x;
y = _ref.y;
console.log(x);
console.log(y);
模板字面量
模板字面量是一種字串字面量,它允許在其中使用表示式。它使用反引號 (``) 而不是單引號或雙引號。當我們在字串中說表示式時,這意味著我們可以在字串中使用變數、呼叫函式等。
示例
let a = 5;
let b = 10;
console.log(`Using Template literal : Value is ${a + b}.`);
console.log("Using normal way : Value is " + (a + b));
輸出
Using Template literal : Value is 15. Using normal way : Value is 15
ES6 - 模板字面量
let a = 5;
let b = 10;
console.log(`Using Template literal : Value is ${a + b}.`);
console.log("Using normal way : Value is " + (a + b));
命令
npx babel templateliteral.js --out-file templateliteral_es5.js
BabelJS - ES5
"use strict";
var a = 5;
var b = 10;
console.log("Using Template literal : Value is " + (a + b) + ".");
console.log("Using normal way : Value is " + (a + b));
增強型物件字面量
在 es6 中,新增到物件字面量的新的特性非常好用。我們將介紹 ES5 和 ES6 中物件字面量的幾個示例:
示例
ES5
var red = 1, green = 2, blue = 3;
var rgbes5 = {
red: red,
green: green,
blue: blue
};
console.log(rgbes5); // {red: 1, green: 2, blue: 3}
ES6
let rgbes6 = {
red,
green,
blue
};
console.log(rgbes6); // {red: 1, green: 2, blue: 3}
如果您看到上面的程式碼,ES5 和 ES6 中的物件有所不同。在 ES6 中,如果變數名與鍵相同,則我們不必指定鍵值。
讓我們看看使用 babel 進行編譯到 ES5 的過程。
ES6-增強型物件字面量
const red = 1, green = 2, blue = 3;
let rgbes5 = {
red: red,
green: green,
blue: blue
};
console.log(rgbes5);
let rgbes6 = {
red,
green,
blue
};
console.log(rgbes6);
let brand = "carbrand";
const cars = {
[brand]: "BMW"
}
console.log(cars.carbrand); //"BMW"
命令
npx babel enhancedobjliteral.js --out-file enhancedobjliteral_es5.js
BabelJS - ES5
"use strict";
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value, enumerable: true, configurable: true, writable: true
});
} else { obj[key] = value; } return obj;
}
var red = 1,
green = 2,
blue = 3;
var rgbes5 = {
red: red,
green: green,
blue: blue
};
console.log(rgbes5);
var rgbes6 = {
red: red,
green: green,
blue: blue
};
console.log(rgbes6);
var brand = "carbrand";
var cars = _defineProperty({}, brand, "BMW");
console.log(cars.carbrand); //"BMW"
預設引數、剩餘引數和擴充套件運算子
在本節中,我們將討論預設引數、剩餘引數和擴充套件運算子。
預設引數
使用 ES6,我們可以對函式引數使用預設引數,如下所示:
示例
let add = (a, b = 3) => {
return a + b;
}
console.log(add(10, 20)); // 30
console.log(add(10)); // 13
讓我們使用 babel 將上述程式碼轉換為 ES5。
命令
npx babel default.js --out-file default_es5.js
BabelJS - ES5
"use strict";
var add = function add(a) {
var b = arguments.length > 1 >> arguments[1] !== undefined ? arguments[1] : 3;
return a + b;
};
console.log(add(10, 20));
console.log(add(10));
剩餘引數
剩餘引數以三個點 (...) 開頭,如下例所示:
示例
let add = (...args) => {
let sum = 0;
args.forEach(function (n) {
sum += n;
});
return sum;
};
console.log(add(1, 2)); // 3
console.log(add(1, 2, 5, 6, 6, 7)); //27
在上面的函式中,我們將 n 個引數傳遞給函式 add。如果在 ES5 中新增所有這些引數,我們必須依賴 arguments 物件來獲取引數的詳細資訊。使用 ES6,rest 幫助使用三個點定義引數,如上所示,我們可以遍歷它並獲得數字的總和。
注意 - 使用三個點,即剩餘引數時,不能使用其他引數。
示例
let add = (...args, value) => { //syntax error
let sum = 0;
args.forEach(function (n) {
sum += n;
});
return sum;
};
上面的程式碼將給出語法錯誤。
編譯到 es5 的結果如下:
命令
npx babel rest.js --out-file rest_es5.js
Babel -ES5
"use strict";
var add = function add() {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
var sum = 0;
args.forEach(function (n) {
sum += n;
});
return sum;
};
console.log(add(1, 2));
console.log(add(1, 2, 5, 6, 6, 7));
擴充套件運算子
擴充套件運算子也像剩餘引數一樣有三個點。以下是一個工作示例,它顯示瞭如何使用擴充套件運算子。
示例
let add = (a, b, c) => {
return a + b + c;
}
let arr = [11, 23, 3];
console.log(add(...arr)); //37
現在讓我們看看使用 babel 如何轉換上面的程式碼:
命令
npx babel spread.js --out-file spread_es5.js
Babel-ES5
"use strict";
var add = function add(a, b, c) {
return a + b + c;
};
var arr = [11, 23, 3];
console.log(add.apply(undefined, arr));
Proxy
Proxy 是一個物件,您可以在其中為屬性查詢、賦值、列舉、函式呼叫等操作定義自定義行為。
語法
var a = new Proxy(target, handler);
target 和 handler 都是物件。
target 是一個物件,也可以是另一個代理元素。
handler 將是一個物件,其屬性為函式,這些函式在呼叫時將提供行為。
讓我們嘗試透過一個示例來了解這些特性:
示例
let handler = {
get: function (target, name) {
return name in target ? target[name] : "invalid key";
}
};
let o = {
name: 'Siya Kapoor',
addr: 'Mumbai'
}
let a = new Proxy(o, handler);
console.log(a.name);
console.log(a.addr);
console.log(a.age);
我們在上面的示例中定義了 target 和 handler,並將其與 proxy 一起使用。Proxy 返回帶有鍵值對的物件。
輸出
Siya Kapoor Mumbai invalid key
現在讓我們看看如何使用Babel將上述程式碼轉換為ES5。
命令
npx babel proxy.js --out-file proxy_es5.js
Babel-ES5
'use strict';
var handler = {
get: function get(target, name) {
return name in target ? target[name] : "invalid key";
}
};
var o = {
name: 'Siya Kapoor',
addr: 'Mumbai'
};
var a = new Proxy(o, handler);
console.log(a.name);
console.log(a.addr);
console.log(a.age);