BabelJS - 快速指南



BabelJS - 概述

BabelJS 是一個 JavaScript 轉換器,它將新特性轉換為舊標準。這樣,這些特性就可以在舊版和新版瀏覽器上無縫執行。一位澳大利亞開發者 Sebastian McKenzie 啟動了 BabelJS。

為什麼選擇 BabelJS?

JavaScript 是瀏覽器理解的語言。我們使用不同的瀏覽器來執行我們的應用程式 - Chrome、Firefox、Internet Explorer、Microsoft Edge、Opera、UC 瀏覽器等。ECMA Script 是 JavaScript 語言規範;ECMA Script 2015 ES6 是穩定的版本,在所有新舊瀏覽器中都能正常工作。

在 ES5 之後,我們有了 ES6、ES7 和 ES8。ES6 釋出了許多新特性,並非所有瀏覽器都完全支援。ES7、ES8 和 ESNext(ECMA Script 的下一個版本)也是如此。目前尚不確定所有瀏覽器何時能夠相容所有釋出的 ES 版本。

如果我們計劃使用 ES6 或 ES7 或 ES8 特性來編寫程式碼,由於缺乏對新更改的支援,它可能會在某些舊版瀏覽器中中斷。因此,如果我們想在程式碼中使用 ECMA Script 的新特性,並希望它在所有可用的瀏覽器上執行,我們需要一個工具將我們的最終程式碼編譯成 ES5。

Babel 做的就是這件事,它被稱為轉換器,可以將程式碼轉換為我們想要的 ECMA Script 版本。它具有預設和外掛等特性,可以配置我們需要轉換程式碼的 ECMA 版本。使用 Babel,開發人員可以使用 JavaScript 中的新特性編寫程式碼。使用者可以使用 Babel 轉換程式碼;這些程式碼隨後可以在任何瀏覽器中使用,而不會出現任何問題。

下表列出了 ES6、ES7 和 ES8 中可用的特性 -

特性 ECMA Script 版本
Let + Const ES6
箭頭函式 ES6
ES6
Promise ES6
生成器 ES6
迭代器 ES6
模組 ES6
解構 ES6
模板字面量 ES6
增強物件 ES6
預設、剩餘和擴充套件屬性 ES6
Async - Await ES7
指數運算子 ES7
Array.prototype.includes() ES7
字串填充 ES8

BabelJS 管理以下兩個部分 -

  • 轉換
  • 填充

什麼是 Babel-轉換器?

Babel-轉換器將現代 JavaScript 的語法轉換為舊版瀏覽器可以輕鬆理解的形式。例如,箭頭函式、const、let 類將轉換為函式、var 等。這裡語法,即箭頭函式被轉換為普通函式,在兩種情況下功能相同。

什麼是 Babel-填充?

JavaScript 中添加了一些新特性,例如 Promise、Map 和 includes。這些特性可以用於陣列;同樣,當使用 Babel 進行轉換時,不會被轉換。如果新特性是方法或物件,我們需要將 Babel-填充與轉換一起使用才能使其在舊版瀏覽器上工作。

以下是 JavaScript 中可用的 ECMA Script 特性列表,可以進行轉換和填充 -

  • 裝飾器
  • Const
  • 模組
  • 解構
  • 預設引數
  • 計算屬性名
  • 物件剩餘/擴充套件
  • 非同步函式
  • 箭頭函式
  • 剩餘引數
  • 擴充套件
  • 模板字面量

可以填充的 ECMA Script 特性 -

  • Promise
  • Map
  • Set
  • Symbol
  • Weakmap
  • Weakset
  • includess
  • Array.from、Array.of、Array#find、Array.buffer、Array#findIndex
  • Object.assign、Object.entries、Object.values

BabelJS 的特性

在本節中,我們將瞭解 BabelJS 的不同特性。以下是 BabelJS 最重要的核心特性 -

Babel-外掛

外掛和預設是 Babel 轉換程式碼的配置細節。Babel 支援許多外掛,如果我們知道程式碼將在哪個環境中執行,則可以單獨使用這些外掛。

Babel-預設

Babel 預設是一組外掛,即 babel-轉換器的配置細節,指示 Babel 以特定模式進行轉換。我們需要使用預設,其中包含我們希望程式碼轉換為的環境。例如,es2015 預設會將程式碼轉換為 es5

Babel-填充

有些特性(例如方法和物件)無法轉換。在這種情況下,我們可以使用 babel-填充來促進在任何瀏覽器中使用這些特性。讓我們以 Promise 為例;為了使該特性在舊版瀏覽器中工作,我們需要使用填充。

Babel-填充

Babel-cli 帶有一系列命令,可以使用這些命令輕鬆地在命令列上編譯程式碼。它還具有外掛和預設等特性,可以與命令一起使用,從而可以輕鬆地一次性轉換程式碼。

使用 BabelJS 的優勢

在本節中,我們將瞭解與使用 BabelJS 相關的不同優勢 -

  • BabelJS 為新增到 JavaScript 的所有新特性提供向後相容性,並且可以在任何瀏覽器中使用。

  • BabelJS 能夠轉換以獲取 JavaScript 的下一個即將釋出的版本 - ES6、ES7、ESNext 等。

  • BabelJS 可以與 gulp、webpack、flow、react、typescript 等一起使用,使其功能非常強大,並且可以用於大型專案,從而使開發人員的生活更輕鬆。

  • BabelJS 還與 react JSX 語法一起使用,並且可以編譯成 JSX 形式。

  • BabelJS 支援外掛、填充、babel-cli,這使得它易於處理大型專案。

使用 BabelJS 的缺點

在本節中,我們將瞭解使用 BabelJS 的不同缺點 -

  • BabelJS 程式碼在轉換時會更改語法,這使得釋出到生產環境後難以理解程式碼。

  • 與原始程式碼相比,轉換後的程式碼大小更大。

  • 並非所有 ES6/7/8 或即將釋出的新特性都可以轉換,我們必須使用填充才能使其在舊版瀏覽器上工作。

這是 babeljs 的官方網站 https://babeljs.io/

Compiler

BabelJS - 環境搭建

在本節中,我們將學習如何為 BabelJS 設定環境。

要使用 BabelJS,我們需要以下設定 -

  • NodeJS
  • Npm
  • Babel-CLI
  • Babel-Preset
  • 用於編寫程式碼的 IDE

NodeJS

要檢查系統中是否安裝了 nodejs,請在終端中鍵入node –v。這將幫助您檢視當前安裝在系統上的 nodejs 版本。

Nodejs

如果它沒有列印任何內容,請在您的系統上安裝 nodejs。要安裝 nodejs,請訪問 nodejs 的主頁 https://nodejs.com.tw/en/download/ 並根據您的作業系統安裝軟體包。

以下螢幕截圖顯示了 nodejs 的下載頁面 -

Download

根據您的作業系統,安裝所需的軟體包。安裝 nodejs 後,npm 也會隨之安裝。要檢查 npm 是否已安裝,請在終端中鍵入npm –v。它應該顯示 npm 的版本。

Command

BabelJS - CLI

Babel 帶有一個內建的命令列介面,可用於編譯程式碼。

建立一個您將在其中工作的目錄。在這裡,我們建立了一個名為babelproject的目錄。讓我們利用 nodejs 建立專案詳細資訊。

我們使用npm init建立專案,如下所示 -

Npm Init

這是我們建立的專案結構。

Project Structure

現在要使用 Babel,我們需要安裝 Babel cli、Babel 預設、Babel 核心,如下所示 -

babel-cli

執行以下命令以安裝 babel-cli -

npm install --save-dev babel-cli

Babel Cli

babel-preset

執行以下命令以安裝 babel-preset -

npm install --save-dev babel-preset-env

Babel Preset

babel-core

執行以下命令以安裝 babel-core -

npm install --save-dev babel-core

Babel Core

安裝後,以下是 package.json 中可用的詳細資訊 -

我們已將 babel 外掛安裝到專案的本地。這樣做是為了我們可以根據專案需求以及 babeljs 的不同版本在專案中以不同的方式使用 babel。Package.json 提供了所用 babeljs 的版本詳細資訊。

為了在專案中使用 babel,我們需要在 package.json 中指定如下 -

Package Json

Babel 主要用於編譯 JavaScript 程式碼,這將具有向後相容性。現在,我們將用 ES6 -> ES5 或 ES7 -> ES5 以及 ES7->ES6 等編寫程式碼。

為了在執行時向 Babel 提供相同的說明,我們需要在根資料夾中建立一個名為 .babelrc 的檔案。它包含一個具有預設詳細資訊的 json 物件,如下所示 -

Json Object

我們將建立 JavaScript 檔案 index.js 並使用 Babel 將其編譯為 es2015。在此之前,我們需要安裝 es2015 預設,如下所示 -

Install es2015

在 index.js 中,我們使用箭頭函式建立了一個函式,這是 es6 中新增的新特性。使用 Babel,我們將程式碼編譯為 es5。

Js_Index

要執行到 es2015,使用以下命令 -

npx babel index.js

輸出

es2015 Output

它顯示了上面所示的 es5 中的 index.js 程式碼。

我們可以透過執行如下命令將輸出儲存到檔案中:

npx babel index.js --out-file index_es5.js

輸出

Execute

這是我們建立的檔案,index_es5.js:

Created Index

BabelJS - ES6 程式碼執行

BabelJS 是一個 JavaScript 編譯器,它將新增到 JavaScript 中的新特性轉換為 ES5 或 React,具體取決於給定的預設或外掛。ES5 是 JavaScript 最古老的形式之一,並且可以無縫執行在新舊瀏覽器上。在本教程的大多數示例中,我們都將程式碼編譯成了 ES5。

我們已經看到了 ES6、ES7 和 ES8 中添加了許多特性,例如箭頭函式、類、Promise、生成器、非同步函式等。當在舊瀏覽器中使用任何新新增的特性時,它都會丟擲錯誤。BabelJS 有助於編譯程式碼,使其向後相容舊版瀏覽器。我們已經看到 ES5 在舊版瀏覽器上執行良好,沒有任何問題。因此,考慮到專案環境的詳細資訊,如果需要在舊版瀏覽器上執行,我們可以在專案中使用任何新特性,並使用 babeljs 將程式碼編譯成 ES5,然後在任何瀏覽器中使用它而不會出現任何問題。

讓我們考慮以下示例來理解這一點。

示例

<!DOCTYPE html>
<html>
   <head>
      <title>BabelJs Testing</title>
   </head>
   <body>
      <script type="text/javascript" src="index.js"></script>
   </body>
</html>

index.js 檔案

var _foo = () => {
   return "Hello World"
};

alert(_foo());

輸出

當我們在 Chrome 瀏覽器中執行以上 html 時,我們得到以下輸出:

Chrome browser

當 HTML 在 Firefox 中執行時,它會生成以下輸出:

Generate

當相同的 HTML 在 Internet Explorer 中執行時,它會生成以下語法錯誤:

Internet Explorer

我們使用了 ES6 箭頭函式;如上所示,它並不適用於所有瀏覽器。為了使其正常工作,我們使用 BabelJS 將程式碼編譯為 ES5,並在所有瀏覽器中使用它。

將使用 babeljs 將 js 檔案編譯為 es5,並在瀏覽器中再次檢查。

Compile es5

在 html 檔案中,我們將使用 index_new.js,如下所示:

<!DOCTYPE html>
<html>
   <head>
      <title>BabelJs Testing</title>
   </head>
   <body>
      <script type="text/javascript" src="index_new.js"></script>
   </body>
</html>

index_new.js

"use strict";

var _foo = function _foo() {
   return "Hello World";
};

alert(_foo());

Chrome 輸出

Chrome Output

Firefox 瀏覽器輸出

Firefox Browser Output

IE 瀏覽器輸出

IE Browser Output

BabelJS - 使用 Babel 6 進行專案設定

在本章中,我們將瞭解如何在專案中使用 babeljs。我們將使用 nodejs 建立一個專案,並使用 http 本地伺服器來測試我們的專案。

建立專案設定

在本節中,我們將學習如何建立專案設定。

建立一個新目錄並執行以下命令建立專案:

npm init

輸出

執行後,上述命令會生成以下輸出:

Npm Init Output

以下是建立的 package.json:

Package Json Create

我們將安裝開始使用 babeljs 所需的軟體包。我們將執行以下命令來安裝babel-cli、babel-core、babel-preset-es2015

npm install babel-cli babel-core babel-preset-es2015 --save-dev

輸出

執行後,上述命令會生成以下輸出:

Npm Install Output

Package.json 更新如下:

Package Json Update

我們需要 http 伺服器來測試 js 檔案。執行以下命令安裝 http 伺服器:

npm install lite-server --save-dev

我們在 package.json 中添加了以下詳細資訊:

Install http server

在指令碼中,Babel 負責將 src 資料夾中的 scripts.js 轉換為 dev 資料夾中的 scripts.bundle.js。我們在 package.json 中添加了編譯所需程式碼的完整命令。此外,添加了build,它將啟動lite-server 來測試更改。

src/scripts.js 中的 JavaScript 如下所示:

class Student {
   constructor(fname, lname, age, address) {
      this.fname = fname;
      this.lname = lname;
      this.age = age;
      this.address = address;
   }

   get fullname() {
      return this.fname +"-"+this.lname;
   }
}

我們在 index.html 中呼叫了轉換後的指令碼,如下所示:

<html>
   lt;head></head>
   <body>
      <script type="text/javascript" src="dev/scripts.bundle.js?a=11"></script>
      <h1 id="displayname"></h1>
      <script type="text/javascript">
         var a = new Student("Siya", "Kapoor", "15", "Mumbai");
         var studentdet = a.fullname;
         document.getElementById("displayname").innerHTML = studentdet;
      </script>
   </body>
</html>

我們需要執行以下命令,它將呼叫 babel 並編譯程式碼。該命令將從 package.json 呼叫 Babel:

npm run babel

Call Babel

scripts.bundle.js 是在 dev 資料夾中建立的新 js 檔案:

New js file

dev/scripts.bundle.js 的輸出如下:

"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 Student = function () {
   function Student(fname, lname, age, address) {
      _classCallCheck(this, Student);

      this.fname = fname;
      this.lname = lname;
      this.age = age;
      this.address = address;
   }

   _createClass(Student, [{
      key: "fullname",
      get: function get() {
         return this.fname + "-" + this.lname;
      }
   }]);

   return Student;
}();

現在讓我們執行以下命令來啟動伺服器:

npm run build

當命令執行時,它將在瀏覽器中開啟 url:

Npm Commond Run

輸出

上述命令生成以下輸出:

Npm Commond Run Output

BabelJS - 使用 Babel 7 進行專案設定

Babel 的最新版本 7 釋出了對現有軟體包的更改。安裝部分與 Babel 6 相同。Babel 7 中唯一的區別是所有軟體包都需要使用@babel/安裝,例如 @babel/core、@babel/preset-env、@babel/cli、@babel/polyfill 等。

這是一個使用 babel 7 建立的專案設定。

命令

執行以下命令啟動專案設定:

npm init

安裝以下軟體包

npm install --save-dev @babel/core
npm install --save-dev @babel/cli
npm install --save-dev @babel/preset-env

以下是建立的 package.json:

Install Packages

現在將在根資料夾中建立一個.babelrc檔案:

Create Babelrc

建立一個資料夾src/並在其中新增檔案main.js,並將您的程式碼寫入轉換為 es5。

src/main.js

let add = (a,b) => {
   return a+b;
}

轉換命令

npx babel src/main.js --out-file main_es5.js

main_es5.js

"use strict";

var add = function add(a, b) {
   return a + b;
};

Babel 7 的工作原理與 Babel 6 相同。唯一的區別是使用 @babel 安裝軟體包。

Babel 7 中有一些預設已棄用。列表如下:

  • ES20xx 預設
  • babel-preset-env
  • babel-preset-latest
  • Babel 中的階段預設

此外,軟體包中的年份也被刪除 - @babel/plugin-transform-es2015-classes現在為@babel/plugin-transform-classes

我們將再舉一個使用 typescript 並使用 typescript 預設和 babel 7 將其轉換為 Es2015 JavaScript 的示例。

要使用 typescript,我們需要安裝 typescript 軟體包,如下所示:

npm install --save-dev @babel/preset-typescript

src/資料夾中建立test.ts檔案,並以 typescript 形式編寫程式碼:

test.ts

let getName = (person: string) => {
   return "Hello, " + person;
}

getName("Siya");

.babelrc

Babelrc Typescript

命令

npx babel src/test.ts --out-file test.js

test.js

"use strict";

var getName = function getName(person) {
   return "Hello, " + person;
};

getName("Siya");

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

從 es6 到 es5 的 let 關鍵字的輸出如下:

使用 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 的狀態為 pending。

Promise 有三種狀態:

  • pending(初始狀態)
  • resolved(成功完成)
  • rejected(失敗)

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-polyfills 的詳細資訊在 babel - poyfill 章節中進行了說明。

生成器

生成器函式類似於普通的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迴圈的更改。但是 iterator.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>

輸出

Babel polyfill

解構

解構屬性的行為類似於 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

在以上函式中,我們向 add 函式傳遞了 n 個引數。如果在 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));

代理

代理是一個物件,您可以在其中定義屬性查詢、賦值、列舉、函式、呼叫等操作的自定義行為。

語法

var a = new Proxy(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);

我們在以上示例中定義了目標和處理程式,並將其與代理一起使用。代理返回帶有鍵值對的物件。

輸出

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);

BabelJS - 將 ES6 模組轉換為 ES5

在本章中,我們將瞭解如何使用 Babel 將 ES6 模組轉換為 ES5。

模組

考慮這樣一種情況:需要重用 JavaScript 程式碼的部分內容。ES6 透過模組的概念來解決這個問題。

模組只不過是寫在檔案中的 JavaScript 程式碼塊。除非模組檔案匯出它們,否則模組中的函式或變數不可用於使用。

簡單來說,模組可以幫助您在模組中編寫程式碼,並僅公開程式碼中其他部分應訪問的部分。

讓我們考慮一個示例,以瞭解如何使用模組以及如何匯出它以便在程式碼中使用它。

示例

add.js

var add = (x,y) => {
   return x+y;
}

module.exports=add;

multiply.js

var multiply = (x,y) => {
   return x*y;
};

module.exports = multiply;

main.js

import add from './add';
import multiply from './multiply'

let a = add(10,20);
let b = multiply(40,10);

console.log("%c"+a,"font-size:30px;color:green;");
console.log("%c"+b,"font-size:30px;color:green;");

我有三個檔案:add.js 用於新增兩個給定數字,multiply.js 用於將兩個給定數字相乘,以及 main.js,它呼叫 add 和 multiply 並輸出控制檯。

為了在 main.js 中使用 add.jsmultiply.js,我們必須首先匯出它們,如下所示。

module.exports = add;
module.exports = multiply;

要在 main.js 中使用它們,我們需要匯入它們,如下所示。

import add from './add';
import multiply from './multiply'

我們需要模組打包器來構建檔案,以便我們可以在瀏覽器中執行它們。

我們可以這樣做:

  • 使用 Webpack
  • 使用 Gulp

ES6 模組和 Webpack

在本節中,我們將瞭解 ES6 模組是什麼。我們還將學習如何使用 webpack。

在開始之前,我們需要安裝以下包。

npm install --save-dev webpack
npm install --save-dev webpack-dev-server
npm install --save-dev babel-core
npm install --save-dev babel-loader
npm install --save-dev babel-preset-env

Package.json

ES6 modules Webpack

我們在指令碼中添加了 pack 和 publish 任務,以便使用 npm 執行它們。以下是 webpack.config.js 檔案,它將構建最終檔案。

webpack.config.js

var path = require('path');

module.exports = {
   entry: {
      app: './src/main.js'
   },
   output: {
      path: path.resolve(__dirname, 'dev'),
      filename: 'main_bundle.js'
   },
   mode:'development',
   module: {
      rules: [
         {
            test: /\.js$/,
            include: path.resolve(__dirname, 'src'),
            loader: 'babel-loader',
            query: {
               presets: ['env']
            }
         }
      ]
   }
};

執行命令 npm run pack 來構建檔案。最終檔案將儲存在 dev/ 資料夾中。

命令

npm run pack

Npm Run Pack

建立了 dev/main_bundle.js 通用檔案。此檔案將 add.js、multiply.js 和 main.js 組合在一起,並將其儲存在 dev/main_bundle.js 中。

/******/ (function(modules) { // webpackBootstrap
/******/    // The module cache
/******/    var installedModules = {};
/******/
/******/    // The require function
/******/    function __webpack_require__(moduleId) {
/******/
/******/       // Check if module is in cache
/******/       if(installedModules[moduleId]) {
/******/          return installedModules[moduleId].exports;
/******/       }
/******/       // Create a new module (and put it into the cache)
/******/       var module = installedModules[moduleId] = {
/******/          i: moduleId,
/******/          l: false,
/******/          exports: {}
/******/       };
/******/
/******/       // Execute the module function
/******/       modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/       // Flag the module as loaded
/******/       module.l = true;
/******/
/******/       // Return the exports of the module
/******/       return module.exports;
/******/    }
/******/
/******/
/******/    // expose the modules object (__webpack_modules__)
/******/    __webpack_require__.m = modules;
/******/
/******/    // expose the module cache
/******/    __webpack_require__.c = installedModules;
/******/
/******/    // define getter function for harmony exports
/******/    __webpack_require__.d = function(exports, name, getter) {
/******/       if(!__webpack_require__.o(exports, name)) {
/******/          Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/       }
/******/    };
/******/
/******/    // define __esModule on exports
/******/    __webpack_require__.r = function(exports) {
/******/      if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/         Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/      }
/******/      Object.defineProperty(exports, '__esModule', { value: true });
/******/    };
/******/
/******/    // create a fake namespace object
/******/    // mode & 1: value is a module id, require it
/******/    // mode & 2: merge all properties of value into the ns
/******/    // mode & 4: return value when already ns object
/******/    // mode & 8|1: behave like require
/******/    __webpack_require__.t = function(value, mode) {
/******/       if(mode & 1) value = __webpack_require__(value);
/******/       if(mode & 8) return value;
/******/       if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/       var ns = Object.create(null);
/******/       __webpack_require__.r(ns);
/******/       Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/       if(mode & 2 && typeof value != 'string')
               for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/       return ns;
/******/    };
/******/
/******/    // getDefaultExport function for compatibility with non-harmony modules
/******/    __webpack_require__.n = function(module) {
/******/       var getter = module && module.__esModule ?
/******/       function getDefault() { return module['default']; } :
/******/       function getModuleExports() { return module; };
/******/       __webpack_require__.d(getter, 'a', getter);
/******/       return getter;
/******/    };
/******/
/******/    // Object.prototype.hasOwnProperty.call
/******/     __webpack_require__.o = function(object, property) {
               return Object.prototype.hasOwnProperty.call(object, property); 
            };
/******/
/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "";
/******/
/******/
/******/    // Load entry module and return exports
/******/    return __webpack_require__(__webpack_require__.s = "./src/main.js");
/******/ })
/************************************************************************/
/******/ ({
/***/       "./src/add.js":
/*!********************!*\
!*** ./src/add.js ***!
\********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
   "use strict";

   eval(
      "\n\nvar add = function add(x, y) {\n return x + y;\n};
      \n\nmodule.exports = add;
      \n\n//# sourceURL = webpack:///./src/add.js?"
   );
   /***/ }),
/***/ "./src/main.js":
/*!*********************!*\
!*** ./src/main.js ***!
\*********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

      "use strict";
      eval(
         "\n\nvar _add = __webpack_require__(/*! ./add */ \"./src/add.js\");
         \n\nvar _add2 = _interopRequireDefault(_add);
         \n\nvar _multiply = __webpack_require__(/*! ./multiply */ \"./src/multiply.js\");
         \n\nvar _multiply2 = _interopRequireDefault(_multiply);
         \n\nfunction _interopRequireDefault(obj) {
            return obj &gt;&gt; obj.__esModule ? obj : { default: obj };
         }
         \n\nvar a = (0, _add2.default)(10, 20);
         \nvar b = (0, _multiply2.default)(40, 10);
         \n\nconsole.log(\"%c\" + a, \"font-size:30px;color:green;\");
         \nconsole.log(\"%c\" + b, \"font-size:30px;color:green;\");
         \n\n//# sourceURL = webpack:///./src/main.js?"
      );

/***/ }),

/***/ "./src/multiply.js":
/*!*************************!*\
   !*** ./src/multiply.js ***!
   \*************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
eval(
   "\n\nvar multiply = function multiply(x, y) {\n return x * y;\n};
   \n\nmodule.exports = multiply;
   \n\n//# sourceURL = webpack:///./src/multiply.js?"
);

/***/ })

/******/ });

命令

以下是在瀏覽器中測試輸出的命令。

npm run publish

NPM Run Publish

在您的專案中新增 index.html。它呼叫 dev/main_bundle.js。

<html>
   <head></head>
   <body>
      <script type="text/javascript" src="dev/main_bundle.js"></script>
   </body>
</html>

輸出

Main Bundle

ES6 模組和 Gulp

要使用 Gulp 將模組捆綁到一個檔案中,我們將使用 browserify 和 babelify。首先,我們將建立專案設定並安裝所需的包。

命令

npm init

在開始專案設定之前,我們需要安裝以下包。

npm install --save-dev gulp
npm install --save-dev babelify
npm install --save-dev browserify
npm install --save-dev babel-preset-env
npm install --save-dev babel-core
npm install --save-dev gulp-connect
npm install --save-dev vinyl-buffer
npm install --save-dev vinyl-source-stream

安裝後的 package.json

After

現在讓我們建立 gulpfile.js,它將幫助執行將模組捆綁在一起的任務。我們將使用上面與 webpack 一起使用的相同檔案。

示例

add.js

var add = (x,y) => {
   return x+y;
}

module.exports=add;

multiply.js

var multiply = (x,y) => {
   return x*y;
};

module.exports = multiply;

main.js

import add from './add';
import multiply from './multiply'

let a = add(10,20);
let b = multiply(40,10);

console.log("%c"+a,"font-size:30px;color:green;");
console.log("%c"+b,"font-size:30px;color:green;");

此處建立了 gulpfile.js。使用者將使用 browserify 並使用 transform 轉換為 babelify。babel-preset-env 用於將程式碼轉換為 es5。

Gulpfile.js

const gulp = require('gulp');
const babelify = require('babelify');
const browserify = require('browserify');
const connect = require("gulp-connect");
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');

gulp.task('build', () => {
   browserify('src/main.js')
   .transform('babelify', {
      presets: ['env']
   })
   .bundle()
   .pipe(source('main.js'))
   .pipe(buffer())
   .pipe(gulp.dest('dev/'));
});
gulp.task('default', ['es6'],() => {
   gulp.watch('src/app.js',['es6'])
});

gulp.task('watch', () => {
   gulp.watch('./*.js', ['build']);
});

gulp.task("connect", function () {
   connect.server({
      root: ".",
      livereload: true
   });
});

gulp.task('start', ['build', 'watch', 'connect']);

我們使用 browserify 和 babelify 來處理模組匯出和匯入,並將它們組合到一個檔案中,如下所示。

gulp.task('build', () => {
   browserify('src/main.js')
   .transform('babelify', {
      presets: ['env']
   })
   .bundle()
   .pipe(source('main.js'))
   .pipe(buffer())
   .pipe(gulp.dest('dev/'));
});

我們在 transform 中呼叫了帶有 presets env 的 babelify。

將包含 main.js 的 src 資料夾提供給 browserify 並儲存在 dev 資料夾中。

我們需要執行命令 gulp start 來編譯檔案。

命令

npm start

Start

以下是 dev/ 資料夾中建立的最終檔案。

(function() {
   function r(e,n,t) {
      function o(i,f) {
         if(!n[i]) {
            if(!e[i]) {
               var c = "function"==typeof require&&require;
               if(!f&&c)return c(i,!0);if(u)return u(i,!0);
               var a = new Error("Cannot find module '"+i+"'");
               throw a.code = "MODULE_NOT_FOUND",a
            }
            var p = n[i] = {exports:{}};
            e[i][0].call(
               p.exports,function(r) {
                  var n = e[i][1][r];
                  return o(n||r)
               }
            ,p,p.exports,r,e,n,t)
         }
         return n[i].exports
      }
      for(var u="function"==typeof require>>require,i = 0;i<t.length;i++)o(t[i]);return o
   }
   return r
})()
({1:[function(require,module,exports) {
   "use strict";

   var add = function add(x, y) {
      return x + y;
   };

   module.exports = add;
},{}],2:[function(require,module,exports) {
   'use strict';

   var _add = require('./add');
   var _add2 = _interopRequireDefault(_add);
   var _multiply = require('./multiply');
   var _multiply2 = _interopRequireDefault(_multiply);
   function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
   var a = (0, _add2.default)(10, 20);
   var b = (0, _multiply2.default)(40, 10);

   console.log("%c" + a, "font-size:30px;color:green;");
   console.log("%c" + b, "font-size:30px;color:green;");
},
{"./add":1,"./multiply":3}],3:[function(require,module,exports) {
   "use strict";

   var multiply = function multiply(x, y) {
      return x * y;
   };

   module.exports = multiply;

},{}]},{},[2]);

我們將它用於 index.html,並在瀏覽器中執行它以獲取輸出。

<html>
   <head></head>
   <body>
      <h1>Modules using Gulp</h1>
      <script type="text/javascript" src="dev/main.js"></script>
   </body>
</html>

輸出

Modules Using Gulp

BabelJS - 將 ES7 特性轉換為 ES5

在本章中,我們將學習如何將 ES7 特性轉換為 ES5。

ECMA Script 7 添加了以下新特性。

  • 非同步-等待
  • 指數運算子
  • Array.prototype.includes()

我們將使用 babeljs 將它們編譯為 ES5。根據您的專案需求,還可以將程式碼編譯為任何 ecma 版本,例如 ES7 到 ES6 或 ES7 到 ES5。由於 ES5 版本最穩定並且在所有現代和舊版瀏覽器上都能正常工作,因此我們將程式碼編譯為 ES5。

非同步-等待

Async 是一個非同步函式,它返回一個隱式 Promise。Promise 要麼被 fulfilled 要麼被 rejected。非同步函式與普通標準函式相同。該函式可以具有 await 表示式,該表示式會暫停執行,直到它返回一個 Promise,一旦獲得 Promise,執行就會繼續。只有當函式為非同步函式時,await 才能工作。

以下是一個關於非同步和等待的工作示例。

示例

let timer = () => {
   return new Promise(resolve => {
      setTimeout(() => {
         resolve("Promise resolved after 5 seconds");
      }, 5000);
   });
};
let out = async () => {
   let msg = await timer();
   console.log(msg);
   console.log("hello after await");
};
out();

輸出

Promise resolved after 5 seconds
hello after await

在呼叫 timer 函式之前添加了 await 表示式。timer 函式將在 5 秒後返回 Promise。因此,await 將暫停執行,直到 timer 函式上的 Promise 被 fulfilled 或 rejected,然後繼續執行。

現在讓我們使用 babel 將以上程式碼轉換為 ES5。

ES7 - 非同步-等待

let timer = () => {
   return new Promise(resolve => {
      setTimeout(() => {
         resolve("Promise resolved after 5 seconds");
      }, 5000);
   });
};
let out = async () => {
   let msg = await timer();
   console.log(msg);
   console.log("hello after await");
};
out();

命令

npx babel asyncawait.js --out-file asyncawait_es5.js

BabelJS - ES5

"use strict";

var timer = function timer() {
   return new Promise(function (resolve) {
      setTimeout(function () {
         resolve("Promise resolved after 5 seconds");
      }, 5000);
   });
};
var out = async function out() {
   var msg = await timer();
   console.log(msg);
   console.log("hello after await");
};

out();

Babeljs 不會編譯物件或方法;因此,此處使用的 Promise 不會被轉換,並將按原樣顯示。為了在舊版瀏覽器上支援 Promise,我們需要新增程式碼,這些程式碼將支援 Promise。現在,讓我們安裝 babel-polyfill,如下所示。

npm install --save babel-polyfill

它應該被儲存為依賴項,而不是開發依賴項。

要在瀏覽器中執行程式碼,我們將使用 node_modules\babel-polyfill\dist\polyfill.min.js 中的 polyfill 檔案,並使用 script 標籤呼叫它,如下所示。

<!DOCTYPE html>
<html>
   <head>
      <title>BabelJs Testing</title>
   </head>
   <body>
      <script src="node_modules\babel-polyfill\dist\polyfill.min.js" type="text/javascript"></script>
      <script type="text/javascript" src="aynscawait_es5.js"></script>
   </body>
</html>

當您執行以上測試頁面時,您將在控制檯中看到以下輸出。

polyfill file

指數運算子

** 是 ES7 中用於冪運算的運算子。以下示例展示了 ES7 中其工作原理,以及使用 babeljs 轉換的程式碼。

示例

let sqr = 9 ** 2;
console.log(sqr);

輸出

81

ES6 - 冪運算

let sqr = 9 ** 2;
console.log(sqr);

要轉換冪運算子,我們需要安裝一個外掛,如下所示。

命令

npm install --save-dev babel-plugin-transform-exponentiation-operator

將外掛詳細資訊新增到 .babelrc 檔案中,如下所示。

{
   "presets":[
      "es2015"
   ],
   "plugins": ["transform-exponentiation-operator"]
}

命令

npx babel exponeniation.js --out-file exponeniation_es5.js

BabelJS - ES5

"use strict";

var sqr = Math.pow(9, 2);
console.log(sqr);

Array.prototype.includes()

如果傳遞給它的元素存在於陣列中,則此特性返回 true,否則返回 false。

示例

let arr1 = [10, 6, 3, 9, 17];
console.log(arr1.includes(9));
let names = ['Siya', 'Tom', 'Jerry', 'Bean', 'Ben'];
console.log(names.includes('Tom'));
console.log(names.includes('Be'));

輸出

true
true
false

我們必須再次使用 babel-polyfill,因為 includes 是陣列上的方法,它不會被轉換。我們需要額外的步驟來包含 polyfill 以使其在舊版瀏覽器中工作。

ES6 - array.includes

let arr1 = [10, 6, 3, 9, 17];
console.log(arr1.includes(9));
let names = ['Siya', 'Tom', 'Jerry', 'Bean', 'Ben'];
console.log(names.includes('Tom'));
console.log(names.includes('Be'));

命令

npx babel array_include.js --out-file array_include_es5.js

Babel-ES5

'use strict';

var arr1 = [10, 6, 3, 9, 17];
console.log(arr1.includes(9));
var names = ['Siya', 'Tom', 'Jerry', 'Bean', 'Ben'];
console.log(names.includes('Tom'));
console.log(names.includes('Be'));

要在舊版瀏覽器中測試它,我們需要使用 polyfill,如下所示。

<!DOCTYPE html>
<html>
   <head>
      <title>BabelJs Testing</title>
   </head>
   <body>
      <script src="node_modules\babel-polyfill\dist\polyfill.min.js" type="text/javascript"></script>
      <script type="text/javascript" src="array_include_es5.js"></script>
   </body>
</html>

輸出

Babel ES5

BabelJS - 將 ES8 特性轉換為 ES5

字串填充是新增到 javascript 中的新 ES8 特性。我們將研究一個簡單的示例,該示例將使用 babel 將字串填充轉換為 ES5。

字串填充

字串填充根據指定的長度從左側新增另一個字串。字串填充的語法如下所示。

語法

str.padStart(length, string);
str.padEnd(length, string);

示例

const str = 'abc';

console.log(str.padStart(8, '_'));
console.log(str.padEnd(8, '_'));

輸出

_____abc
abc_____

ES8 - 字串填充

const str = 'abc';

console.log(str.padStart(8, '_'));
console.log(str.padEnd(8, '_'));

命令

npx babel strpad.js --out-file strpad_es5.js

Babel - ES5

'use strict';

var str = 'abc';

console.log(str.padStart(8, '_'));
console.log(str.padEnd(8, '_'));

js 必須與 babel-polyfill 一起使用,如下所示。

test.html

<!DOCTYPE html>
<html>
   <head>
      <title>BabelJs Testing</title>
   </head>
   <body>
      <script src="node_modules\babel-polyfill\dist\polyfill.min.js" type="text/javascript"></script>
      <script type="text/javascript" src="strpad_es5.js"></script>
   </body>
</html>

String Padding

BabelJS - Babel 外掛

BabelJS 是一個 JavaScript 編譯器,它根據可用的預設和外掛更改給定程式碼的語法。Babel 編譯流程涉及以下三個部分。

  • 解析
  • 轉換
  • 列印

傳遞給 Babel 的程式碼會原樣返回,只是語法發生了改變。我們已經看到過將預設新增到 .babelrc 檔案中,以將程式碼從 es6 編譯到 es5 或反之亦然。預設只不過是一組外掛。如果在編譯期間未提供預設或外掛的詳細資訊,Babel 不會進行任何更改。

現在讓我們討論以下外掛 -

  • transform-class-properties
  • Transform-exponentiation-operator
  • For-of
  • 物件 rest 和擴充套件
  • async/await

現在,我們將建立一個專案設定並使用一些外掛進行操作,這將使我們對 Babel 中外掛的需求有更清晰的瞭解。

命令

npm init

我們必須為 Babel 安裝所需的包 - Babel CLI、Babel Core、Babel 預設等。

Babel 6 的包

npm install babel-cli babel-core babel-preset-es2015 --save-dev

Babel 7 的包

npm install @babel/cli @babel/core @babel/preset-env --save-dev

在你的專案中建立一個 js 檔案並編寫你的 js 程式碼。

類 - Transform-class-properties

為此,請觀察以下給出的程式碼 -

示例

main.js

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;

目前,我們還沒有向 Babel 提供任何預設或外掛的詳細資訊。如果我們碰巧使用以下命令轉換程式碼 -

npx babel main.js --out-file main_out.js

main_out.js

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;

我們將獲得與程式碼相同的輸出。現在讓我們將預設新增到 .babelrc 檔案中。

注意 - 在專案根目錄下建立 .babelrc 檔案。

.babelrc for babel 6

Babelrc For Babel

.babelrc for babel 7

{
   "presets":["@babel/env"]
}

我們已經安裝了預設;現在讓我們再次執行命令 -

npx babel main.js --out-file main_out.js

main_out.js

"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;

在 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;
   }
}

存在建構函式,並且類的所有屬性都在其中定義。如果我們需要在類外部定義類屬性,則無法這樣做。

示例

class Person {
   name = "Siya Kapoor";

   fullname = () => {
      return this.name;
   }
}
var a = new Person();
var persondet = a.fullname();
console.log("%c"+persondet, "font-size:25px;color:red;");

如果我們碰巧編譯上述程式碼,它將在 Babel 中丟擲一個錯誤。這導致程式碼無法編譯。

Error In Babel

為了使其按我們想要的方式工作,我們可以使用名為 babel-plugin-transform-class-properties 的 Babel 外掛。為了使其工作,我們需要先安裝它,如下所示 -

Babel 6 的包

npm install --save-dev babel-plugin-transform-class-properties

Babel 7 的包

npm install --save-dev @babel/plugin-proposal-class-properties

將外掛新增到 .babelrc 檔案中以供 Babel 6 使用 -

Add Plugin Babelrc

.babelrc for babel 7

{
   "plugins": ["@babel/plugin-proposal-class-properties"]
}

現在,我們將再次執行命令。

命令

npx babel main.js --out-file main_out.js

main.js

class Person {
   name = "Siya Kapoor";

   fullname = () => {
      return this.name;
   }
}
var a = new Person();
var persondet = a.fullname();
console.log("%c"+persondet, "font-size:25px;color:red;");

編譯到 main_out.js

class Person {
   constructor() {
      this.name = "Siya Kapoor";

      this.fullname = () => {
         return this.name;
      };
   }
}
var a = new Person();
var persondet = a.fullname();
console.log("%c"+persondet, "font-size:25px;color:red;");

輸出

以下是我們在瀏覽器中使用時獲得的輸出 -

Babelrc Output

指數運算子 - transform-exponentiation-operator

** 是 ES7 中用於指數運算的運算子。以下示例顯示了 ES7 中相同運算子的工作原理。它還展示瞭如何使用 BabelJS 轉換程式碼。

示例

let sqr = 9 ** 2;
console.log("%c"+sqr, "font-size:25px;color:red;");

要轉換指數運算子,我們需要安裝以下外掛 -

Babel 6 的包

npm install --save-dev babel-plugin-transform-exponentiation-operator

Babel 7 的包

npm install --save-dev @babel/plugin-transform-exponentiation-operator

將外掛詳細資訊新增到 .babelrc 檔案中,如下所示,以供 Babel 6 使用 -

{
   "plugins": ["transform-exponentiation-operator"]
}

.babelrc for babel 7

{
   "plugins": ["@babel/plugin-transform-exponentiation-operator"]
}

命令

npx babel exponeniation.js --out-file exponeniation_out.js

exponeniation_out.js

let sqr = Math.pow(9, 2);
console.log("%c" + sqr, "font-size:25px;color:red;");

輸出

Exponeniation Output

For-of

Babel 6 和 7 中外掛所需的包如下 -

Babel 6

npm install --save-dev babel-plugin-transform-es2015-for-of

Babel 7

npm install --save-dev @babel/plugin-transform-for-of

.babelrc for babel 6

{
   "plugins": ["transform-es2015-for-of"]
}

.babelrc for babel 7

{
   "plugins": ["@babel/plugin-transform-for-of"]
}

forof.js

let foo = ["PHP", "C++", "Mysql", "JAVA"];
for (var i of foo) {
   console.log(i);
}

命令

npx babel forof.js --out-file forof_es5.js

Forof_es5.js

let foo = ["PHP", "C++", "Mysql", "JAVA"];
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;

try {
   for (var _iterator = foo[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
      var i = _step.value;

      console.log(i);
   }
} catch (err) {
   _didIteratorError = true;
   _iteratorError = err;
} finally {
   try {
      if (!_iteratorNormalCompletion && _iterator.return) {
         _iterator.return();
      }
   } finally {
      if (_didIteratorError) {
         throw _iteratorError;
      }
   }
}

輸出

Forof es5 Output

物件 rest 和擴充套件

Babel 6 和 7 中外掛所需的包如下 -

Babel 6

npm install --save-dev babel-plugin-transform-object-rest-spread

Babel 7

npm install --save-dev @babel/plugin-proposal-object-rest-spread

.babelrc for babel 6

{
   "plugins": ["transform-object-rest-spread"]
}

.babelrc for babel 7

{
   "plugins": ["@babel/plugin-proposal-object-rest-spread"]
}

o.js

let { x1, y1, ...z1 } = { x1: 11, y1: 12, a: 23, b: 24 };
console.log(x1);
console.log(y1);
console.log(z1);

let n = { x1, y1, ...z1};
console.log(n);

命令

npx babel o.js --out-file o_es5.js

o_es5.js

var _extends = Object.assign || function (target) {
   for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i]; for (var key in source) {
         if (Object.prototype.hasOwnProperty.call(source, key)) {
            target[key] = source[key]; 
         } 
      } 
   } 
   return target; 
};

function _objectWithoutProperties(obj, keys) {
   var target = {};
   for (var i in obj) {
      if (keys.indexOf(i) >= 0) continue;
      if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
      target[i] = obj[i];
   }
   return target;
}

let _x1$y1$a$b = { x1: 11, y1: 12, a: 23, b: 24 },
   { x1, y1 } = _x1$y1$a$b,
   z1 = _objectWithoutProperties(_x1$y1$a$b, ["x1", "y1"]);
console.log(x1);
console.log(y1);
console.log(z1);

let n = _extends({ x1, y1 }, z1);
console.log(n);

輸出

Object Rest Spread Output

async/await

我們需要為 Babel 6 安裝以下包 -

npm install --save-dev babel-plugin-transform-async-to-generator

Babel 7 的包

npm install --save-dev @babel/plugin-transform-async-to-generator

.babelrc for babel 6

{
   "plugins": ["transform-async-to-generator"]
}

.babelrc for babel 7

{
   "plugins": ["@babel/plugin-transform-async-to-generator"]
}

async.js

let timer = () => {
   return new Promise(resolve => {
      setTimeout(() => {
         resolve("Promise resolved after 5 seconds");
      }, 5000);
   });
};
let out = async () => {
   let msg = await timer();
   console.log(msg);
   console.log("hello after await");
};

out();

命令

npx babel async.js --out-file async_es5.js

async_es5.js

function _asyncToGenerator(fn) {
   return function () {
      var gen = fn.apply(this, arguments);
      return new Promise(function (resolve, reject) {
         function step(key, arg) {
            try {
               var info = gen[key](arg);
               var value = info.value; 
            } catch (error) {
               reject(error);
               return; 
            } if (info.done) {
               resolve(value); 
            } else {
               return Promise.resolve(value).then(function (value) {
                  step("next", value);
               },
               function (err) {
                  step("throw", err); }); 
            }
         } return step("next"); 
      });
   };
}

let timer = () => {
   return new Promise(resolve => {
      setTimeout(() => {
         resolve("Promise resolved after 5 seconds");
      }, 5000);
   });
};
let out = (() => {
   var _ref = _asyncToGenerator(function* () {
      let msg = yield timer();
      console.log(msg);
      console.log("hello after await");
   });

   return function out() {
      return _ref.apply(this, arguments);
   };
})();
out();

我們必須為此使用 polyfill,因為它在不支援 Promise 的瀏覽器中不起作用。

輸出

Async es5 output

BabelJS - Babel Polyfill

Babel Polyfill 為 Web 瀏覽器添加了對尚不可用功能的支援。Babel 將程式碼從最新的 Ecma 版本編譯到我們想要的版本。它根據預設更改語法,但無法對使用的物件或方法執行任何操作。我們必須為這些功能使用 polyfill 以實現向後相容性。

可以進行 polyfill 的功能

以下是當在舊版瀏覽器中使用時需要 polyfill 支援的功能列表 -

  • Promise
  • Map
  • Set
  • Symbol
  • Weakmap
  • Weakset
  • Array.from、Array.includes、Array.of、Array#find、Array.buffer、Array#findIndex
  • Object.assign、Object.entries、Object.values

我們將建立專案設定,並檢視 Babel Polyfill 的工作原理。

命令

npm init

我們現在將安裝 Babel 所需的包。

Babel 6 的包

npm install babel-cli babel-core babel-preset-es2015 --save-dev

Babel 7 的包

npm install @babel/cli @babel/core @babel/preset-env --save-dev

這是最終的 package.json -

Final Package Json

我們還將 es2015 新增到預設中,因為我們希望將程式碼編譯到 es5。

.babelrc for babel 6

Babelrc

.babelrc for babel 7

{
   "presets":["@babel/env"]
}

我們將安裝 lite-serve,以便我們可以在瀏覽器中測試程式碼 -

npm install --save-dev lite-server

讓我們將 Babel 命令新增到 package.json 中以編譯我們的程式碼 -

Babel Command

我們還添加了 build 命令,該命令呼叫 lite-server。

Babel-polyfill 與 babel-core 包一起安裝。babel-polyfill 將在 node_modules 中可用,如下所示 -

Node Modules

我們將進一步研究 Promise 並與之一起使用 babel-polyfill。

ES6 - Promise

let timingpromise = new Promise((resolve, reject) => {
   setTimeout(function() {
      resolve("Promise is resolved!");
   }, 1000);
});

timingpromise.then((msg) => {
   console.log("%c"+msg, "font-size:25px;color:red;");
});

命令

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("%c"+msg, "font-size:25px;color:red;");
});

編譯不需要更改任何內容。Promise 的程式碼已原樣轉換。但是,即使我們將程式碼編譯到 es5,不支援 Promise 的瀏覽器也會丟擲錯誤。

要解決此問題,我們需要在最終的 es5 編譯程式碼中新增 polyfill。要在瀏覽器中執行程式碼,我們將從 node_modules 中獲取 babel-polyfill 檔案並將其新增到我們要使用 Promise 的 .html 檔案中,如下所示 -

index.html

<html>
   <head>
   </head>
   <body>
      <h1>Babel Polyfill Testing</h1>
      <script type="text/javascript" src="node_modules/babel-polyfill/dist/polyfill.min.js"></script>
      <script type="text/javascript" src="promise_es5.js"></script>
   </body>
</html>

輸出

Babel Polyfill Testing

在 index.html 檔案中,我們使用了來自 node_modules 的 polyfill.min.js 檔案,然後是 promise_es5.js -

<script type="text/javascript" src="node_modules/babel-polyfill/dist/polyfill.min.js"></script>

<script type="text/javascript" src="promise_es5.js"></script>

注意 - polyfill 檔案必須在主 JavaScript 呼叫之前開始使用。

字串填充

字串填充根據指定的長度從左側新增另一個字串。字串填充的語法如下所示。

語法

str.padStart(length, string);
str.padEnd(length, string);

示例

const str = 'abc';

console.log(str.padStart(8, '_'));
console.log(str.padEnd(8, '_'));

輸出

_____abc
abc_____

Babel - ES5

npx babel strpad.js --out-file strpad_es5.js

命令

'use strict';

var str = 'abc';

console.log(str.padStart(8, '_'));
console.log(str.padEnd(8, '_'));

js 必須與 babel-polyfill 一起使用,如下所示。

test.html

<!DOCTYPE html>
<html>
   <head>
      <title>BabelJs Testing </title>
   </head>
   <body>
      <script src="node_modules/babel-polyfill/dist/polyfill.min.js" type="text/javascript"></script>
      <script type="text/javascript" src="strpad_es5.js"></script>
   </body>
</html>

String Padding Output

Map、Set、WeakSet、WeakMap

在本節中,我們將學習Map、Set、WeakSet、WeakMap。

  • Map 是一個具有鍵/值對的物件。

  • Set 也是一個物件,但具有唯一值。

  • WeakMap 和 WeakSet 也是具有鍵/值對的物件。

Map、Set、WeakMap 和 WeakSet 是新增到 ES6 中的新功能。要將其轉換為在舊版瀏覽器中使用,我們需要使用 polyfill。我們將使用一個示例並使用 polyfill 編譯程式碼。

示例

let m = new Map(); //map example
m.set("0","A");
m.set("1","B");
console.log(m);

let set = new Set(); //set example
set.add('A');
set.add('B');
set.add('A');
set.add('B');
console.log(set);

let ws = new WeakSet(); //weakset example
let x = {};
let y = {};
ws.add(x);
console.log(ws.has(x));
console.log(ws.has(y));

let wm = new WeakMap(); //weakmap example
let a = {};
wm.set(a, "hello");
console.log(wm.get(a));

輸出

Map(2) {"0" => "A", "1" => "B"}
Set(2) {"A", "B"}
true
false
hello

命令

npx babel set.js --out-file set_es5.js

Babel-ES5

"use strict";

var m = new Map(); //map example
m.set("0", "A");
m.set("1", "B");
console.log(m);

var set = new Set(); //set example
set.add('A');
set.add('B');
set.add('A');
set.add('B');
console.log(set);

var ws = new WeakSet(); //weakset example
var x = {};
var y = {};
ws.add(x);
console.log(ws.has(x));
console.log(ws.has(y));

var wm = new WeakMap(); //weakmap example
var a = {};
wm.set(a, "hello");
console.log(wm.get(a));

js 必須與 babel-polyfill 一起使用,如下所示。

test.html

<!DOCTYPE html>
<html>
   <head>
      <title>BabelJs Testing</title>
   </head>
   <body>
      <script src="node_modules/babel-polyfill/dist/polyfill.min.js" type="text/javascript"></script>
      <script type="text/javascript" src="set_es5.js"></script>
   </body>
</html>

輸出

WeakMap Output

陣列方法

可以在陣列上使用許多屬性和方法;例如,array.from、array.includes 等。

讓我們考慮使用以下示例來更好地理解這一點。

示例

arraymethods.js

var arrNum = [1, 2, 3];

console.log(arrNum.includes(2));
console.log(Array.from([3, 4, 5], x => x + x));

輸出

true
[6, 8, 10]

命令

npx babel arraymethods.js --out-file arraymethods_es5.js

Babel-es5

"use strict";

var arrNum = [1, 2, 3];

console.log(arrNum.includes(2));
console.log(Array.from([3, 4, 5], function (x) {
return x + x;
}));

陣列上使用的方法按原樣列印。為了使其在舊版瀏覽器上工作,我們需要在開頭新增 polyfill 檔案,如下所示 -

index.html

<html>
   <head></head>
   <body>
      <h1>Babel Polyfill Testing</h1>
      <script type="text/javascript" src="node_modules/babel-polyfill/dist/polyfill.min.js"></script>
      <script type="text/javascript" src="arraymethods_es5.js"></script>
   </body>
</html>

輸出

Array Methods Js

BabelJS - Babel CLI

BabelJS 帶有一個內建的命令列介面,其中可以使用易於使用的命令輕鬆地將 JavaScript 程式碼編譯到相應的 ECMA Script。我們將在本章中討論這些命令的使用。

首先,我們將為我們的專案安裝 babel-cli。我們將使用 babeljs 編譯程式碼。

為你的專案建立一個資料夾以使用 babel-cli。

命令

npm init

顯示

Display

為上述專案建立的 Package.json -

Display Json

讓我們執行命令來安裝 babel-cli。

Babel 6 的包

npm install --save-dev babel-cli

Babel 7 的包

npm install --save-dev @babel/cli

顯示

Install Package

我們已經安裝了 babel-cli,這是更新後的 package.json -

Updated Package

此外,我們需要安裝 babel-preset 和 babel-core。現在讓我們看看安裝命令。

Babel 6 的包

npm install --save-dev babel-preset-env
npm install --save-dev babel-core

Babel 7 的包

npm install --save-dev @babel/core
npm install --save-dev @babel/preset-env

這是上述命令的更新後的 package.json -

Updated Package Json

由於我們需要編譯我們將要編寫的 JavaScript 程式碼以具有向後相容性,因此我們將將其編譯為 ECMA Script 5。為此,我們需要指示 Babel 查詢預設,即將在其中進行編譯的 es 版本。我們需要在建立的專案根目錄中建立一個 .babelrc> 檔案,如下所示。

它包含一個具有以下預設詳細資訊的 json 物件 -

{ "presets": ["env"] }

對於 Babel 7,.babelrc 如下所示 -

{
   "presets":["@babel/env"]
}

我們已將 Babel 本地安裝到專案中。為了在我們的專案中使用 Babel,我們需要在 package.json 中指定它,如下所示 -

Installed Babel Local

編譯 JS 檔案

現在我們準備編譯我們的 JavaScript 檔案了。在你的專案中建立一個名為 src 的資料夾;在這個資料夾中,建立一個名為 main.js 的檔案並編寫如下所示的 es6 javascript 程式碼 -

命令

npx babel src/main.js

輸出

Compile JS

在上述情況下,來自 main.js 的程式碼在終端中以 es5 版本顯示。來自 es6 的箭頭函式轉換為 es5,如上所示。我們將儲存在不同的檔案中,而不是在終端中顯示編譯後的程式碼,如下所示。

我們在專案中建立了一個名為 out 的資料夾,我們希望將編譯後的檔案儲存在其中。以下命令將編譯並將輸出儲存在我們想要的位置。

命令

npx babel src/main.js --out-file out/main_out.js

輸出

Compile JS Output

命令中的 --out-file 選項幫助我們將輸出儲存在我們選擇的資料夾位置。

如果我們希望每次更改主要檔案時都更新檔案,請將 --watch-w 選項新增到命令中,如下所示。

命令

npx babel src/main.js --watch --out-file out/main_out.js

輸出

Updated File Output

你可以對主要檔案進行更改;此更改將反映在編譯後的檔案中。

在上述情況下,我們更改了日誌訊息,並且 --watch 選項持續檢查是否有任何更改,並在編譯後的檔案中添加了相同的更改。

Change Main File

編譯後的檔案

Compiled file

在我們之前的章節中,我們學習瞭如何編譯單個檔案。現在,我們將編譯一個目錄並將編譯後的檔案儲存在另一個目錄中。

在 src 資料夾中,我們將建立另一個 js 檔案,名為 main1.js。目前,src 資料夾中有 2 個 javascript 檔案 main.jsmain1.js

以下是檔案中的程式碼 -

main.js

var arrowfunction = () => {
   console.log("Added changes to the log message");
}

main1.js

var handler = () => {
   console.log("Added one more file");
}

以下命令將編譯來自 src 資料夾的程式碼並將其儲存到 out/ 資料夾中。我們已從 out/ 資料夾中刪除所有檔案並將其清空。我們將執行該命令並檢查 out/ 資料夾中的輸出。

命令

npx babel src --out-dir out

我們在 out 資料夾中得到了 2 個檔案 - main.js 和 main1.js

main.js

"use strict";

var arrowfunction = function arrowfunction() {
   console.log("Added changes to the log message");
};

main1.js

"use strict";

var handler = function handler() {
   console.log("Added one more file");
};

接下來,我們將執行以下命令以使用 babeljs 將這兩個檔案編譯成一個檔案。

命令

npx babel src --out-file out/all.js

輸出

"use strict";

var arrowfunction = function arrowfunction() {
   console.log("Added changes to the log message");
};
"use strict";

var handler = function handler() {
console.log("Added one more file");
};

如果我們希望忽略某些檔案不被編譯,我們可以使用 --ignore 選項,如下所示。

命令

npx babel src --out-file out/all.js --ignore src/main1.js

輸出

all.js

"use strict";

var arrowfunction = function arrowfunction() {
   console.log("Added changes to the log message");
};

我們可以使用外掛選項在檔案編譯期間使用。要使用外掛,我們需要安裝它,如下所示。

命令

npm install --save-dev babel-plugin-transform-exponentiation-operator

expo.js

let sqr = 9 ** 2;
console.log(sqr);

命令

npx babel expo.js --out-file expo_compiled.js --plugins=babel-plugin-transform-exponentiation-operator

輸出

"use strict";

var sqr = Math.pow(9, 2);
console.log(sqr);

我們也可以在命令中使用預設,如下所示。

命令

npx babel src/main.js --out-file main_es5.js --presets=es2015

為了測試上述情況,我們已從 .babelrc 中刪除了預設選項。

main.js

var arrowfunction = () => {
   console.log("Added changes to the log message");
}

main_es5.js

"use strict";

var arrowfunction = function arrowfunction() {
   console.log("Added changes to the log message");
};

我們也可以從命令列忽略 .babelrc,如下所示 -

npx babel --no-babelrc src/main.js --out-file main_es5.js --presets=es2015

為了測試上述情況,我們已將預設添加回 .babelrc,並且由於我們在命令中添加了 --no-babelrc,因此它將被忽略。main_es5.js 檔案的詳細資訊如下 -

main_es5.js

"use strict";

var arrowfunction = function arrowfunction() {
   console.log("Added changes to the log message");
};

BabelJS - Babel 預設

Babel 預設是 Babel 轉換器的配置詳細資訊,告訴它以指定的模式進行轉換。以下是一些我們將在本章中討論的最流行的預設 -

  • ES2015
  • Env
  • React

我們需要使用包含我們希望程式碼轉換到的環境的預設。例如,es2015 預設會將程式碼轉換為 es5。值為 env 的預設也會轉換為 es5。它還具有其他功能,即選項。如果您希望該功能在最新版本的瀏覽器上受支援,則 Babel 僅在這些瀏覽器不支援該功能時才會轉換程式碼。使用 react 預設,Babel 會將程式碼轉換為 React 程式碼。

要使用預設,我們需要在專案根資料夾中建立一個 .babelrc 檔案。為了展示其工作原理,我們將建立一個如下所示的專案結構。

命令

npm init

Work Preset

我們必須按照如下方式安裝所需的 Babel 預設,以及 Babel CLI、Babel Core 等。

Babel 6 包

npm install babel-cli babel-core babel-preset-es2015 --save-dev

Babel 7 包

npm install @babel/cli @babel/core @babel/preset-env --save-dev

注意 - babel-preset-es2015 從 Babel 7 開始已棄用。

es2015 或 @babel/env

在專案的根目錄中建立 .babelrc 檔案 (Babel 6) -

Babelrc env

在 .babelrc 中,預設為 es2015。這表示我們希望 Babel 編譯器將程式碼轉換為 es2015。

對於 Babel 7,我們需要按如下方式使用預設 -

{
   "presets":["@babel/env"]
}

以下是安裝後的 package.json -

Package Json After Installation

由於我們已在本地安裝了 Babel,因此我們在 package.json 的 scripts 部分添加了 Babel 命令。

讓我們做一個簡單的示例來檢查使用 es2015 預設進行轉譯。

示例

main.js

let arrow = () => {
   return "this is es6 arrow function";
}

轉譯為 es5,如下所示。

命令

npx babel main.js --out-file main_es5.js

main_es5.js

"use strict";

var arrow = function arrow() {
   return "this is es6 arrow function";
};

Env

使用 Env 預設,您可以指定您希望最終程式碼轉譯到的環境。

我們將使用上面建立的相同的專案結構,並將預設從 es2015 更改為 env,如下所示。

Change Preset Es2015

此外,我們需要安裝 babel-preset-env。我們將執行以下命令來安裝它。

命令

npm install babel-preset-env --save-dev

我們將再次編譯 main.js 並檢視輸出。

main.js

let arrow = () => {
   return "this is es6 arrow function";
}

命令

npx babel main.js --out-file main_env.js

main_env.js

"use strict";

var arrow = function arrow() {
   return "this is es6 arrow function";
};

我們看到轉譯後的程式碼是 es5。如果我們知道程式碼將執行的環境,我們可以使用此預設來指定它。例如,如果我們將瀏覽器指定為 Chrome 和 Firefox 的最後 1 個版本,如下所示。

Browsers

命令

npx babel main.js --out-file main_env.js

main_env.js

"use strict";

let arrow = () => {
   return "this is es6 arrow function";
};

我們現在獲得的箭頭函式語法保持不變。它沒有被轉譯成 ES5 語法。這是因為我們希望程式碼支援的環境已經支援箭頭函式。

Babel 使用 babel-preset-env 處理基於環境的程式碼編譯。我們還可以根據 Node.js 環境來指定編譯目標,如下所示

Nodejs Environment

程式碼的最終編譯結果如下所示。

命令

npx babel main.js --out-file main_env.js

main_env.js

"use strict";

let arrow = () => {
   return "this is es6 arrow function";
};

Babel 根據當前 Node.js 版本編譯程式碼。

React 預設

當我們使用 React.js 時,可以使用 React 預設。我們將做一個簡單的示例,並使用 React 預設檢視輸出。

要使用預設,我們需要安裝 babel-preset-react (Babel 6),如下所示 -

npm install --save-dev babel-preset-react

對於 Babel 7,如下所示 -

npm install --save-dev @babel/preset-react

對於 Babel 6,.babelrc 的更改如下 -

Change Babelrc

對於 Babel 7

{
   "presets": ["@babel/preset-react"]
}

main.js

<h1>Hello, world!</h1>

命令

npx babel main.js --out-file main_env.js

main_env.js

React.createElement(
   "h1",
   null,
   "Hello, world!"
);

使用預設:react,main.js 中的程式碼被轉換為 React.js 語法。

BabelJS - 使用 Babel 和 Webpack

Webpack 是一個模組打包器,它將所有模組及其依賴項(js、樣式、影像等)打包成靜態資源 .js、.css、.jpg、.png 等。Webpack 帶有預設,有助於將程式碼編譯成所需的格式。例如,React 預設有助於將最終輸出轉換為 React 格式,es2015 或 env 預設有助於將程式碼編譯為 ES5 或 6 或 7 等。我們在專案設定中使用了 Babel 6。如果您想切換到 Babel 7,請使用 @babel/babel-package-name 安裝 Babel 的所需包。

這裡,我們將討論使用 Babel 和 Webpack 的專案設定。建立一個名為 的資料夾,並在 Visual Studio IDE 中開啟它。

要建立專案設定,請執行 npm init babel webpack,如下所示 -

Babel Webpack

以下是 npm init 建立後的 package.json -

Init Webpack

現在,我們將安裝使用 Babel 和 Webpack 所需的包。

npm install --save-dev webpack
npm install --save-dev webpack-dev-server
npm install --save-dev babel-core
npm install --save-dev babel-loader
npm install --save-dev babel-preset-env

以下是安裝後的 Package.json -

Package After Installation

現在,我們將建立一個 webpack.config.js 檔案,其中包含打包 js 檔案的所有詳細資訊。這些檔案將使用 Babel 編譯成 es5。

要使用伺服器執行 Webpack,我們使用 webpack-server。以下是新增到其中的詳細資訊 -

Webpack Server

我們添加了 publish 命令,它將啟動 webpack-dev-server 並更新最終檔案儲存的路徑。現在我們將用於更新最終檔案的路徑是 /dev 資料夾。

要使用 Webpack,我們需要執行以下命令 -

npm run publish

首先我們需要建立 webpack.config.js 檔案。這些檔案將包含 Webpack 工作的配置詳細資訊。

檔案中的詳細資訊如下 -

var path = require('path');

module.exports = {
   entry: {
      app: './src/main.js'
   },
   output: {
      path: path.resolve(__dirname, 'dev'),
      filename: 'main_bundle.js'
   },
   mode:'development',
   module: {
      rules: [
         {
            test: /\.js$/,
            include: path.resolve(__dirname, 'src'),
            loader: 'babel-loader',
            query: {
               presets: ['env']
            }
         }
      ]
   }
};

檔案的結構如上所示。它以 path 開頭,提供當前路徑的詳細資訊。

var path = require('path'); //gives the current path

接下來是 module.exports 物件,它具有 entry、output 和 module 屬性。entry 是起點。在這裡,我們需要提供要編譯的主要 js 檔案。

entry: {
   app: './src/main.js'
},

path.resolve(_dirname, ‘src/main.js’) -- 將在目錄中查詢 src 資料夾,並在該資料夾中查詢 main.js。

輸出

output: {
   path: path.resolve(__dirname, 'dev'),
   filename: 'main_bundle.js'
},

Output 是一個包含 path 和 filename 屬性的物件。Path 將儲存編譯檔案所在的資料夾,filename 將告訴您在 .html 檔案中使用的最終檔名。

module

module: {
   rules: [
      {
         test: /\.js$/,
         include: path.resolve(__dirname, 'src'),
         loader: 'babel-loader',
         query: {
            presets: ['env']
         }
      }
   ]
}
  • Module 是一個包含規則詳細資訊的物件。它具有以下屬性 -

    • test
    • include
    • loader
    • query
  • Test 將儲存所有以 .js 結尾的 js 檔案的詳細資訊。它具有模式,將在給定的入口點中查詢結尾處的 .js。

  • Include 指示要檢視的檔案使用的資料夾。

  • Loader 使用 babel-loader 來編譯程式碼。

  • Query 具有 presets 屬性,它是一個數組,其值為 env - es5 或 es6 或 es7。

建立 src 資料夾和 main.js 檔案;在其中編寫您的 ES6 程式碼。稍後,執行命令以檢視它如何使用 Webpack 和 Babel 編譯為 es5。

src/main.js

let add = (a,b) => {
   return a+b;
};
let c = add(10, 20);
console.log(c);

執行以下命令 -

npm run pack

編譯後的檔案如下所示 -

dev/main_bundle.js

!function(e) {
   var t = {};
   function r(n) {
      if(t[n])return t[n].exports;var o = t[n] = {i:n,l:!1,exports:{}};
      return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports
   }
   r.m = e,r.c = t,r.d = function(e,t,n) {
      r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})
   },
   r.r = function(e) {
      "undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})
   },
   r.t = function(e,t) {
      if(1&t&&(e = r(e)),8&t)return e;
      if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;
      var n = Object.create(null);
      if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t) {return e[t]}.bind(null,o));
      return n
   },
   r.n = function(e) {
      var t = e&&e.__esModule?function() {return e.default}:function() {return e};
      return r.d(t,"a",t),t
   },
   r.o = function(e,t) {return Object.prototype.hasOwnProperty.call(e,t)},
   r.p = "",r(r.s = 0)
}([function(e,t,r) {"use strict";var n = function(e,t) {return e+t}(10,20);console.log(n)}]);
!function(e) {
   var t = {};
   function r(n) {
      if(t[n])return t[n].exports;
      var o = t[n] = {i:n,l:!1,exports:{}};
      return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports
   }
   r.m = e,r.c = t,r.d = function(e,t,n) {
      r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})
   },
   r.r = function(e) {
      "undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})
   },
   r.t = function(e,t) {
      if(1&t&&(e=r(e)),
      8&t)return e;
      if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;
      var n = Object.create(null);
      if(
         r.r(n),
         Object.defineProperty(n,"default",{enumerable:!0,value:e}),
         2&t&&"string"!=typeof e
      )
      for(var o in e)r.d(n,o,function(t) {return e[t]}.bind(null,o));
      return n
   },
   r.n = function(e) {
      var t = e&&e.__esModule?function() {return e.default}:function() {return e};
      return r.d(t,"a",t),t
   },
   r.o = function(e,t) {
      return Object.prototype.hasOwnProperty.call(e,t)
   },
   r.p = "",r(r.s = 0)
}([function(e,t,r) {
   "use strict";
   var n = function(e,t) {return e+t}(10,20);
   console.log(n)
}]);

程式碼如上所示編譯。Webpack 添加了一些內部所需的程式碼,並且 main.js 中的程式碼位於末尾。我們已經像上面那樣控制檯輸出了值。

在 .html 檔案中新增最終的 js 檔案,如下所示 -

<html>
   <head></head>
   <body>
      <script type="text/javascript" src="dev/main_bundle.js"></script>
   </body>
</html>

執行以下命令 -

npm run publish

Module Webpack

要檢查輸出,我們可以在以下地址開啟檔案 -

https://:8080/

Module Webpack Output

我們得到如上所示的控制檯值。現在讓我們嘗試使用 Webpack 和 Babel 將程式碼編譯成單個檔案。

我們將使用 Webpack 將多個 js 檔案捆綁到一個檔案中。Babel 將用於將 es6 程式碼編譯為 es5。

現在,我們在 src/ 資料夾中有 2 個 js 檔案 - main.js 和 Person.js,如下所示 -

person.js

export 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;
   }
}

我們使用了 export 來使用 Person 類的詳細資訊。

main.js

import {Person} from './person'
var a = new Person("Siya", "Kapoor", "15", "Mumbai");
var persondet = a.fullname;
console.log(persondet);

在 main.js 中,我們從檔案路徑匯入了 Person。

注意 - 我們不必包含 person.js,只需檔名即可。我們建立了一個 Person 類的物件,並如上所示控制檯輸出了詳細資訊。

Webpack 將合併 person.jsmain.js,並在 dev/main_bundle.js 中更新為一個檔案。執行命令 npm run publish 以在瀏覽器中檢查輸出 -

Dev Main Bundle

BabelJS - 使用 Babel 和 JSX

在本章中,我們將瞭解使用 JSX 和 Babel 的方法。在深入瞭解細節之前,讓我們先了解什麼是 JSX。

什麼是 JSX?

JSX 是一種 JavaScript 程式碼,其中包含 XML 語法。JSX 標籤具有標籤名稱、屬性和子元素,使其看起來像 XML。

React 使用 JSX 進行模板化,而不是普通的 JavaScript。這不是必須的,但是,以下是一些隨之而來的優點。

  • 它更快,因為它在將程式碼編譯為 JavaScript 時執行最佳化。

  • 它也是型別安全的,大多數錯誤可以在編譯時被捕獲。

  • 如果您熟悉 HTML,它使編寫模板變得更容易和更快。

我們在專案設定中使用了 Babel 6。如果您想切換到 Babel 7,請使用 @babel/babel-package-name 安裝 Babel 的所需包。

我們將建立專案設定並使用 Webpack 將 JSX 與 React 編譯成正常的 JavaScript,使用 Babel。

要啟動專案設定,請執行以下命令以安裝 Babel、React 和 Webpack。

命令

npm init

Webpack Installation

現在,我們將安裝使用 Babel、Webpack 和 JSX 所需的包 -

npm install --save-dev webpack
npm install --save-dev webpack-cli
npm install --save-dev webpack-dev-server
npm install --save-dev babel-core
npm install --save-dev babel-loader
npm install --save-dev babel-preset-es2015
npm install --save-dev babel-preset-react
npm install --save-dev react
npm install --save-dev react-dom

以下是安裝後的 package.json -

Work_With_Babel_Webpack

現在將建立一個 webpack.config.js 檔案,其中包含打包 js 檔案的所有詳細資訊,並使用 Babel 將其編譯成 es5。

要使用伺服器執行 Webpack,有一個名為 webpack-server 的工具。我們添加了一個名為 publish 的命令;此命令將啟動 webpack-dev-server 並更新最終檔案儲存的路徑。現在我們將用於更新最終檔案的路徑是 /dev 資料夾。

要使用 Webpack,我們需要執行以下命令 -

npm run publish

我們將建立 webpack.config.js 檔案,其中包含 Webpack 工作的配置詳細資訊。

檔案中的詳細資訊如下 -

var path = require('path');

module.exports = {
   entry: {
      app: './src/main.js'
   },
   output: {
      path: path.resolve(__dirname, 'dev'),
      filename: 'main_bundle.js'
   },
   mode:'development',
   module: {
      rules: [
         {
            test:/\.(js|jsx)$/,
            include: path.resolve(__dirname, 'src'),
            loader: 'babel-loader',
            query: {
               presets: ['es2015','react']
            }
         }
      ]
   }
};

檔案的結構如上所示。它以 path 開頭,提供當前路徑的詳細資訊。

var path = require('path'); //gives the current path

接下來是 module.exports 物件,它具有 entry、output 和 module 屬性。

Entry 是起點。在這裡,我們需要提供要編譯的主要 js 檔案。

entry: {
   app: './src/main.js'
},

path.resolve(_dirname, ‘src/main.js’) -- 將在目錄中查詢 src 資料夾,並在該資料夾中查詢 main.js

輸出

output: {
   path: path.resolve(__dirname, 'dev'),
   filename: 'main_bundle.js'
},

Output 是一個包含 path 和 filename 屬性的物件。Path 將儲存編譯檔案所在的資料夾,filename 將告訴您在 .html 檔案中使用的最終檔名。

module

module: {
   rules: [
      {
         test:/\.(js|jsx)$/,
         include: path.resolve(__dirname, 'src'),
         loader: 'babel-loader',
         query: {
            presets: ['es2015','react']
         }
      }
   ]
}
  • 模組是一個包含規則細節的物件,它具有屬性,例如 test、include、loader 和 query。

  • Test 將儲存所有以 .js 和 .jsx 結尾的 js 檔案的詳細資訊。它具有一個模式,將在給定的入口點中查詢結尾處的 .js 和 .jsx。

  • Include 指示用於查詢檔案的資料夾。

  • Loader 使用 babel-loader 來編譯程式碼。

  • Query 具有屬性 presets,它是一個數組,其值為 env – es5 或 es6 或 es7。我們使用了 es2015 和 react 作為預設。

建立資料夾 src/。在其中新增 main.jsApp.jsx

App.jsx

import React from 'react';

class App extends React.Component {
   render() {
         var style = {
         color: 'red',
         fontSize: 50
      };
      return (
         <div style={style}>
            Hello World!!!
         </div>
      );
   }
}
export default App;

main.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';

ReactDOM.render(, document.getElementById('app'));

執行以下命令來打包 .js 檔案並使用預設 es2015react 進行轉換。

命令

npm run pack

Convert_Using_Presets

將 dev 資料夾中的 main_bundle.js 新增到 index.html 中 -

<!DOCTYPE html>
<html lang = "en">
   <head>
      <meta charset = "UTF-8">
      <title>React App</title>
   </head>
   <body>
      <div id = "app"></div>
      <script src = "dev/main_bundle.js"></script>
   </body>
</html>

命令

npm run publish

Dev Folder To Index

輸出

Dev Folder To Index Output

BabelJS - 使用 Babel 和 Flow

Flow 是 JavaScript 的靜態型別檢查器。要使用 Flow 和 Babel,我們將首先建立一個專案設定。我們在專案設定中使用了 Babel 6。如果您想切換到 Babel 7,請使用 @babel/babel-package-name 安裝 Babel 的必需包。

命令

npm init

安裝 Flow 和 Babel 的必需包 -

npm install --save-dev babel-core babel-cli babel-preset-flow flow-bin babel-plugin-transform-flow-strip-types

這是安裝後的最終 package.json。還添加了 Babel 和 Flow 命令,以便在命令列中執行程式碼。

Execute_Flow_Command.jpg

在專案設定內建立 .babelrc,並新增如下所示的預設

Add Presets

建立一個 main.js 檔案,並使用 Flow 編寫您的 JavaScript 程式碼 -

main.js

/* @flow */
function concat(a: string, b: string) {
   return a + b;
}

let a = concat("A", "B");
console.log(a);

使用 Babel 命令編譯程式碼,使用預設:將 Flow 轉換為普通 JavaScript

npx babel main.js --out-file main_flow.js

main_flow.js

function concat(a, b) {
   return a + b;
}

let a = concat("A", "B");
console.log(a);

我們還可以使用名為 babel-plugin-transform-flow-strip-types 的外掛來代替預設,如下所示 -

.babelrc 中,新增如下所示的外掛 -

Babelrc Plug

main.js

/* @flow */
function concat(a: string, b: string) {
   return a + b;
}

let a = concat("A", "B");
console.log(a);

命令

npx babel main.js --out-file main_flow.js

main_flow.js

function concat(a, b) {
   return a + b;
}

let a = concat("A", "B");
console.log(a);

BabelJS - 使用 BabelJS 和 Gulp

在本章中,我們將使用 Babel 和 Gulp 建立專案設定。Gulp 是一個使用 Node.js 作為平臺的任務執行器。Gulp 將執行將 JavaScript 檔案從 es6 轉換為 es5 的任務,完成後將啟動伺服器以測試更改。我們在專案設定中使用了 Babel 6。如果您想切換到 Babel 7,請使用 @babel/babel-package-name 安裝 Babel 的必需包。

我們將首先使用 npm 命令建立專案,並安裝所需的包以開始。

命令

npm init

Babel Package Name.

我們建立了一個名為 gulpbabel 的資料夾。接下來,我們將安裝 Gulp 和其他必需的依賴項。

命令

npm install gulp --save-dev
npm install gulp-babel --save-dev
npm install gulp-connect --save-dev
npm install babel-preset-env --save-dev
npm install babel-core --save-dev

Install Gulp

我們將如下所示將預設環境詳細資訊新增到 .babelrc 檔案中

Preset Environment Details

gulpfile.js

var gulp =require('gulp');
var babel =require('gulp-babel');
var connect = require("gulp-connect");
gulp.task('build', () => {
   gulp.src('src/./*.js')
      .pipe(babel())
      .pipe(gulp.dest('./dev'))
});

gulp.task('watch', () => {
   gulp.watch('./*.js', ['build']);
});

gulp.task("connect", function () {
   connect.server({
      root: ".",
      livereload: true
   });
});

gulp.task('start', ['build', 'watch', 'connect']);

我們在 Gulp 中建立了三個任務:[‘build’,’watch’,’connect’]。src 資料夾中所有可用的 js 檔案將使用 Babel 轉換為 es5,如下所示 -

gulp.task('build', () => {
   gulp.src('src/./*.js')
      .pipe(babel())
      .pipe(gulp.dest('./dev'))
});

最終更改儲存在 dev 資料夾中。Babel 使用 .babelrc 中的預設詳細資訊。如果您想更改為其他預設,可以在 .babelrc 檔案中更改詳細資訊。

現在,我們將使用 es6 javascript 在 src 資料夾中建立一個 .js 檔案,並執行 gulp start 命令來執行更改。

src/main.js

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;
   }
}

命令:gulp start

Command Gulp Start

dev/main.js

這是使用 Babel 轉換的 -

"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;
}();

Index.html

這是使用 轉換後的 dev/main.js 完成的 -

<html>
   <head></head>
   <body>
      <script type="text/javascript" src="dev/main.js"></script>
      <h1 id="displayname"></h1>
      <script type="text/javascript">
         var a = new Student("Siya", "Kapoor", "15", "Mumbai");
         var studentdet = a.fullname;
         document.getElementById("displayname").innerHTML = studentdet;
      </script>
   </body>
</html>

輸出

Transpiled Dev Output

BabelJS - 示例

我們將使用 ES6 功能並建立一個簡單的專案。Babeljs 將用於將程式碼編譯為 ES5。該專案將包含一組影像,這些影像將在固定時間間隔後自動滑動。我們將使用 ES6 類來處理它。我們在專案設定中使用了 Babel 6。如果您想切換到 Babel 7,請使用 @babel/babel-package-name 安裝 Babel 的必需包。

自動滑動影像

我們將使用 Gulp 來構建專案。首先,我們將建立如下所示的專案設定

命令

npm init

Auto Slide Images

我們建立了一個名為 babelexample 的資料夾。接下來,我們將安裝 Gulp 和其他必需的依賴項。

命令

npm install gulp --save-dev
npm install gulp-babel --save-dev
npm install gulp-connect --save-dev
npm install babel-preset-env --save-dev

以下是安裝後的 Package.json -

babelexample

我們將如下所示將預設環境詳細資訊新增到 .babelrc 檔案中 -

Babelrc Environment Details

由於我們需要 Gulp 任務來構建最終檔案,因此我們將建立包含所需任務的 gulpfile.js

gulpfile.js

var gulp = require('gulp');
var babel = require('gulp-babel');
var connect = require("gulp-connect");
gulp.task('build', () => {
   gulp.src('src/./*.js')
      .pipe(babel())
      .pipe(gulp.dest('./dev'))
});
gulp.task('watch', () => {
   gulp.watch('./*.js', ['build']);
});

gulp.task("connect", function () {
   connect.server({
      root: ".",
      livereload: true
   });
});

gulp.task('start', ['build', 'watch', 'connect']);

我們在 Gulp 中建立了三個任務,[‘build’,’watch’,’connect’]。src 資料夾中所有可用的 js 檔案將使用 Babel 轉換為 es5,如下所示

gulp.task('build', () => {
   gulp.src('src/./*.js')
      .pipe(babel())
      .pipe(gulp.dest('./dev'))
});

最終更改儲存在 dev 資料夾中。Babel 使用 .babelrc 中的預設詳細資訊。如果您想更改為其他預設,可以在 .babelrc 檔案中更改詳細資訊。

現在,我們將使用 es6 JavaScript 在 src 資料夾中建立一個 .js 檔案,並執行 gulp start 命令來執行更改。

專案結構如下所示 -

Babel Project Structure

src/slidingimage.js

class SlidingImage {
   constructor(width, height, imgcounter, timer) {
      this.counter = 0;
      this.imagecontainerwidth = width;
      this.imagecontainerheight = height;
      this.slidercounter = imgcounter;
      this.slidetimer = timer;
      this.startindex = 1;
      this.css = this.applycss();
      this.maincontainer = this.createContainter();
      this.childcontainer = this.imagecontainer();
      this.autoslide();
   }

   createContainter() {
      let maindiv = document.createElement('div');
      maindiv.id = "maincontainer";
      maindiv.class = "maincontainer";
      document.body.appendChild(maindiv);
      return maindiv;
   }

   applycss() {
      let slidercss = ".maincontainer{ position : relative; margin :auto;}.left, 
         .right {
            cursor: pointer; position: absolute;" +
            "top: 50%; width: auto; padding: 16px; margin-top: -22px; color: white; font-weight: bold; " +
            "font-size: 18px; transition: 0.6s ease; border-radius: 0 3px 3px 0;
         }.right { right: 0; border-radius: 3px 0 0 3px;}" +
         ".left:hover, .right:hover { background-color: rgba(0,0,0,0.8);}";
      let style = document.createElement('style');
      style.id = "slidercss";
      style.type = "text/css";
      document.getElementsByTagName("head")[0].appendChild(style);
      let styleall = style;
      if (styleall.styleSheet) {
      styleall.styleSheet.cssText = slidercss;
      } else {
         let text = document.createTextNode(slidercss);
         style.appendChild(text);
      }
   }

   imagecontainer() {
      let childdiv = [];
      let imgcont = [];
      for (let a = 1; a >= this.slidercounter; a++) {
         childdiv[a] = document.createElement('div');
         childdiv[a].id = "childdiv" + a;
         childdiv[a].style.width = this.imagecontainerwidth + "px";
         childdiv[a].style.height = this.imagecontainerheight + "px";
         if (a > 1) {
            childdiv[a].style.display = "none";
         }
         imgcont[a] = document.createElement('img');
         imgcont[a].src = "src/img/img" + a + ".jpg";
         imgcont[a].style.width = "100%";
         imgcont[a].style.height = "100%";
         childdiv[a].appendChild(imgcont[a]);
         this.maincontainer.appendChild(childdiv[a]);
      }
   }

   autoslide() {
      console.log(this.startindex);
      let previousimg = this.startindex;
      this.startindex++;
      if (this.startindex > 5) {
         this.startindex = 1;
      }
      setTimeout(() => {
         document.getElementById("childdiv" + this.startindex).style.display = "";
         document.getElementById("childdiv" + previousimg).style.display = "none";
         this.autoslide();
      }, this.slidetimer);
   }
}

let a = new SlidingImage(300, 250, 5, 5000);    

我們將建立 src/ 中的 img/ 資料夾,因為我們需要顯示影像;這些影像需要每 5 秒旋轉一次。dev/ 資料夾將儲存編譯後的程式碼。執行 gulp start 以構建最終檔案。

最終專案結構如下所示 -

Final Project Structure

slidingimage.js 中,我們建立了一個名為 SlidingImage 的類,該類具有諸如 createcontainer、imagecontainer 和 autoslide 等方法,這些方法建立主容器並將影像新增到其中。autoslide 方法有助於在指定的時間間隔後更改影像。

let a = new SlidingImage(300, 250, 5, 5000);

在此階段,將呼叫該類。我們將傳遞 寬度、高度、影像數量和旋轉影像的秒數

命令

gulp start

Rotate Image

dev/slidingimage.js

"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 SlidingImage = function () {
   function SlidingImage(width, height, imgcounter, timer) {
      _classCallCheck(this, SlidingImage);
      this.counter = 0;
      this.imagecontainerwidth = width;
      this.imagecontainerheight = height;
      this.slidercounter = imgcounter;
      this.slidetimer = timer;
      this.startindex = 1;
      this.css = this.applycss();
      this.maincontainer = this.createContainter();
      this.childcontainer = this.imagecontainer();
      this.autoslide();
   }
   _createClass(SlidingImage, [{
      key: "createContainter",
      value: function createContainter() {
         var maindiv = document.createElement('div');
         maindiv.id = "maincontainer";
         maindiv.class = "maincontainer";
         document.body.appendChild(maindiv);
         return maindiv;
      }
   }, {
      key: "applycss",
      value: function applycss() {
         var slidercss = ".maincontainer{ position : relative; margin :auto;}.left, .right {
            cursor: pointer; position: absolute;" + "top: 50%;
            width: auto;
            padding: 16px;
            margin-top: -22px;
            color: white;
            font-weight: bold;
            " + "font-size: 18px;
            transition: 0.6s ease;
            border-radius: 0 3px 3px 0;
         }
         .right { right: 0; border-radius: 3px 0 0 3px;}" +
            ".left:hover, .right:hover { background-color: rgba(0,0,0,0.8);}";
         var style = document.createElement('style');
         style.id = "slidercss";
         style.type = "text/css";
         document.getElementsByTagName("head")[0].appendChild(style);
         var styleall = style;
         if (styleall.styleSheet) {
            styleall.styleSheet.cssText = slidercss;
         } else {
            var text = document.createTextNode(slidercss);
            style.appendChild(text);
         }
      }
   }, {
      key: "imagecontainer",
      value: function imagecontainer() {
      var childdiv = [];
      var imgcont = [];
      for (var _a = 1; _a <= this.slidercounter; _a++) {
         childdiv[_a] = document.createElement('div');
         childdiv[_a].id = "childdiv" + _a;
         childdiv[_a].style.width = this.imagecontainerwidth + "px";
         childdiv[_a].style.height = this.imagecontainerheight + "px";
         if (_a > 1) {
            childdiv[_a].style.display = "none";
         }
         imgcont[_a] = document.createElement('img');
         imgcont[_a].src = "src/img/img" + _a + ".jpg";
         imgcont[_a].style.width = "100%";
         imgcont[_a].style.height = "100%";
         childdiv[_a].appendChild(imgcont[_a]);
         this.maincontainer.appendChild(childdiv[_a]);
         }
      }
   }, {
      key: "autoslide",
      value: function autoslide() {
         var _this = this;

         console.log(this.startindex);
         var previousimg = this.startindex;
         this.startindex++;
         if (this.startindex > 5) {
            this.startindex = 1;
         }
         setTimeout(function () {
            document.getElementById("childdiv" + _this.startindex).style.display = "";
            document.getElementById("childdiv" + previousimg).style.display = "none";
            _this.autoslide();
         }, this.slidetimer);
      }
   }]);
   return SlidingImage;
}();

var a = new SlidingImage(300, 250, 5, 5000);

我們將如下所示在瀏覽器中測試程式碼行 -

index.html

<html>
   <head></head>
   <body>
      <script type="text/javascript" src="dev/slidingimage.js"></script>
      <h1>Sliding Image Demo</h1>
   </body>
</html>

我們在 index.html 中使用了 dev 資料夾中的編譯檔案。命令 gulp start 啟動伺服器,我們可以在其中測試輸出。

在 Chrome 中

Sliding Image Chrome

在 Firefox 中

Sliding Image Firefox

在 Internet Explorer 中

sliding Image IE

編譯後的程式碼在所有瀏覽器中都能正常工作。

廣告

© . All rights reserved.