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 中可用的功能 −

Features ECMA Script version
Let + Const ES6
Arrow Functions ES6
Classes ES6
Promises ES6
Generators ES6
Iterators ES6
Modules ES6
Destructuring ES6
Template Literals ES6
Enhanced Object ES6
Default, Rest & Spread Properties ES6
Async - Await ES7
Exponentiation Operator ES7
Array.prototype.includes() ES7
String Padding ES8

BabelJS 管理以下两个部分 −

  • 转译
  • polyfilling

什么是 Babel-Transpiler?

Babel-transpiler 将现代 JavaScript 的语法转换为旧版浏览器可以轻松理解的形式。例如,箭头函数、const、let 类将转换为函数、var 等。在这里,语法(即箭头函数)转换为普通函数,在两种情况下保持功能相同。

什么是 Babel-polyfill?

JavaScript 中添加了新功能,如承诺、映射和包含。这些功能可用于数组;同样,当使用 babel 进行转译时,不会被转换。如果新功能是方法或对象,我们需要使用 Babel-polyfill 和转译功能使其在旧版浏览器上运行。

以下是 JavaScript 中可用的 ECMA Script 功能列表,可以进行转译和 polyfill −

  • Classes
  • Decorators
  • Const
  • Modules
  • Destructing
  • Default parameters
  • Computed property names
  • Object rest/spread
  • Async functions
  • Arrow functions
  • Rest parameters
  • Spread
  • Template Literals

可以实现 polyfill 的 ECMA Script 功能 −

  • Promises
  • 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-Plugins

插件和预设是 Babel 转译代码的配置详细信息。Babel 支持许多插件,如果我们知道代码将在哪个环境中执行,则可以单独使用这些插件。

Babel-Presets

Babel 预设是一组插件,即 babel-transpiler 的配置详细信息,指示 Babel 以特定模式进行转译。我们需要使用预设,它具有我们希望代码转换的环境。例如,es2015 预设会将代码转换为 es5

Babel-Polyfills

有些功能(如方法和对象)无法转译。在这种情况下,我们可以利用 babel-polyfill 来方便在任何浏览器中使用这些功能。让我们考虑一下承诺的例子;为了让该功能在旧版浏览器中发挥作用,我们需要使用 polyfills。

Babel-Polyfills

Babel-cli 附带了一堆命令,可以在命令行上轻松编译代码。它还具有插件和预设等功能,可与命令一起使用,从而可以轻松地一次性转译代码。

使用 BabelJS 的优势

在本节中,我们将了解使用 BabelJS 的不同优势 −

  • BabelJS 为 JavaScript 的所有新添加功能提供向后兼容性,并且可以在任何浏览器中使用。

  • BabelJS 能够转译以采用下一个即将推出的 JavaScript 版本 - ES6、ES7、ESNext 等。

  • BabelJS 可以与 gulp、webpack、flow、react、typescript 等一起使用,功能非常强大,可以用于大型项目,让开发人员的工作变得轻松。

  • BabelJS 还可以与 react JSX 语法一起使用,并且可以在 JSX 中编译形式。

  • BabelJS 支持插件、polyfill、babel-cli,可轻松处理大型项目。

使用 BabelJS 的缺点

在本节中,我们将了解使用 BabelJS 的不同缺点 −

  • BabelJS 代码在转译时会更改语法,这使得代码在发布到生产环境时难以理解。

  • 与原始代码相比,转译后的代码更大。

  • 并非所有 ES6/7/8 或即将推出的新功能都可以转译,我们必须使用 polyfill 才能使其在旧版浏览器上运行。

这是 babeljs 的官方网站 https://babeljs.io/

Compiler

BabelJS - 环境设置

在本节中,我们将学习如何为 BabelJS 设置环境。

要使用 BabelJS,我们需要进行以下设置 −

  • NodeJS
  • Npm
  • Babel-CLI
  • Babel-Preset
  • IDE for writing code

NodeJS

要检查您的系统上是否安装了 nodejs,请在终端中输入 node –v。这将帮助您查看系统上当前安装的 nodejs 版本。

Nodejs

如果它没有打印任何内容,请在您的系统上安装 nodejs。要安装 nodejs,请转到 nodejs 的主页 https://nodejs.org/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 preset、Babel core,如下所示 −

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 或根据给定的预设或插件做出反应。ES5 是最古老的 JavaScript 形式之一,支持在新旧浏览器上运行而不会出现任何问题。在本教程中的大多数示例中,我们已将代码转译为 ES5。

我们已经看到许多功能,如箭头函数、类、承诺、生成器、异步函数等,都添加到了 ES6、ES7 和 ES8。当任何新添加的功能在旧浏览器中使用时,都会抛出错误。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 file

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

alert(_foo());

输出

当我们在 Chrome 浏览器中运行上述 html 时,我们得到以下输出 −

Chrome browser

当 HTML 在 Firefox 中运行时,它会生成以下输出 −

Generate

当相同的 HTML 在 Internet Explorer 中运行时,它会生成以下语法错误 −

Internet Explorer

我们使用了 ES6 Arrow 函数;如上所示,该函数并非在所有浏览器上都有效。为了实现这一点,我们使用 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 输出

Firefox 浏览器输出

Firefox 浏览器输出

IE 浏览器输出

IE 浏览器输出

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 中添加了以下详细信息 −

安装 http 服务器

在脚本中,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
调用 Babel

scripts.bundle.js 是在 dev 文件夹中创建的新 js 文件 −

新 js 文件

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 −

安装包

现在将在根文件夹中创建一个 .babelrc 文件 −

创建 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 presets
  • babel-preset-env
  • babel-preset-latest
  • Stage presets in 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
  • Arrow Functions
  • Classes
  • Promises
  • Generators
  • Destructuring
  • Iterators
  • Template Literalst
  • Enhanced Object
  • Default, Rest & Spread Properties

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-loop 等。

现在我们将看到使用 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 未在 :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 - Classes

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;

Promises

JavaScript Promises 用于管理代码中的异步请求。

当您管理具有依赖关系的异步请求的多个回调时,它使生活更轻松,并保持代码整洁。Promises 提供了一种使用回调函数的更好方法。Promises 是 ES6 的一部分。默认情况下,当您创建 Promises 时,Promises 的状态为待处理。

Promises 有三种状态 −

  • pending (initial state)
  • resolved (completed successfully)
  • rejected(failed)

new Promise() 用于构造 Promise。Promise 构造函数有一个参数,即回调函数。回调函数有两个参数 - resolve 和 rejection;

这两个都是内部函数。您编写的异步代码,即 Ajax 调用、图像加载、计时函数将进入回调函数。

如果回调函数中执行的任务成功,则调用 resolve 函数;否则,使用错误详细信息调用 rejection 函数。

以下代码行显示了 promise 结构调用 −

var _promise = new Promise (function(resolve, reject) {
   var success = true;
   if (success) {
      resolve("success");
   } else {
      reject("failure");
   }
});
_promise.then(function(value) {
    //一旦函数 resolve 被调用,它就会带着传入 resolve 的值到这里
    console.log(value); //成功
}).catch(function(value) {
    //一旦函数 rejection 被调用,它就会带着传入 rejection 的值到这里
    console.log(value); //失败。
});

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 - Promises

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

对于承诺,代码在转译时不会改变。我们需要使用 babel-polyfill 才能使其在旧版浏览器上运行。babel-polyfill 的详细信息在 babel - poyfill 章节中进行了说明。

生成器

生成器函数与普通函数类似。该函数具有特殊语法 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 - Generator

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

输出给出一个具有值和 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 中使用,如下所示 −

Example

<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(`使用模板文字:值为 ${a + b}。`);
console.log("使用正常方式:值为 " + (a + b));

输出

使用模板文字:值为 15。
使用正常方式:值为 15

ES6 - 模板文字

let a = 5;
let b = 10;
console.log(`使用模板文字:值为 ${a + b}。`);
console.log("使用正常方式:值为 " + (a + b));

命令

npx babel templateliteral.js --out-file templateliteral_es5.js

BabelJS - ES5

"use strict";

var a = 5;
var b = 10;
console.log("使用模板文字:值为 " + (a + b) + "。");

console.log("使用正常方式:值为 " + (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));

Rest

剩余参数以三个点 (...) 开头,如下例所示 −

示例

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 中,要添加所有这些参数,我们必须依赖参数对象来获取参数的详细信息。在 ES6 中,rest it 有助于用三个点定义参数,如上所示,我们可以循环遍历它并获取数字的总和。

注意 − 使用三个点(即 rest)时,我们不能使用其他参数。

示例

let add = (...args, value) => { //语法错误
   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));

Spread

Spread 属性也像 rest 一样有三个点。以下是一个工作示例,展示了如何使用 spread 属性。

示例

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 是一个对象,您可以在其中为属性查找、赋值、枚举、函数、调用等操作定义自定义行为。

语法

var a = new Proxy(target, handler);

targethandler 都是对象。

  • 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,用于将 2 个给定数字相加,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

我们已将打包和发布任务添加到脚本中,以便使用 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
/******/    // 模块缓存
/******/    var installedModules = {};
/******/
/******/    // The require function
/******/    function __webpack_require__(moduleId) {
/******/
/******/       // 检查模块是否在缓存中
/******/       if(installedModules[moduleId]) {
/******/          return installedModules[moduleId].exports;
/******/       }
/******/       // 创建一个新模块(并将其放入缓存中)
/******/       var module = installedModules[moduleId] = {
/******/          i: moduleId,
/******/          l: false,
/******/          exports: {}
/******/       };
/******/
/******/       // 执行模块函数
/******/       modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/       // 将模块标记为已加载
/******/       module.l = true;
/******/
/******/       // 返回模块的导出
/******/       return module.exports;
/******/    }
/******/
/******/
/******/    // 公开模块对象(__webpack_modules__)
/******/    __webpack_require__.m = modules;
/******/
/******/    // 公开模块缓存
/******/    __webpack_require__.c = installedModules;
/******/
/******/    // 为 harmony 导出定义 getter 函数
/******/    __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 });
/******/    };
/******/
/******/ // 创建一个假的命名空间对象
/******/ // 模式 & 1:值是一个模块 ID,需要它
/******/ // 模式 & 2:将值的所有属性合并到 ns
/******/ // 模式 & 4:当已经是 ns 对象时返回值
/******/ // 模式 & 8|1:表现得像需要
/******/    __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 函数用于兼容非 Harmony 模块
/******/    __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(
      "

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

module.exports = add;
      

//# sourceURL = webpack:///./src/add.js?"
   );
   /***/ }),
/***/ "./src/main.js":
/*!*********************!*\
!*** ./src/main.js ***!
\*********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

      "use strict";
      eval(
         "

var _add = __webpack_require__(/*! ./add */ \"./src/add.js\");
         

var _add2 = _interopRequireDefault(_add);
         

var _multiply = __webpack_require__(/*! ./multiply */ \"./src/multiply.js\");
         

var _multiply2 = _interopRequireDefault(_multiply);
         

function _interopRequireDefault(obj) {
            return obj &gt;&gt; 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;\");
         

//# sourceURL = webpack:///./src/main.js?"
      );

/***/ }),

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

"use strict";
eval(
   "

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

module.exports = multiply;
   

//# 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 一起使用的相同文件。

Example

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 在此处创建。用户将浏览器化并使用转换进行 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,其中使用预设环境调用了 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>

输出

使用 Gulp 的模块

BabelJS - 将 ES7 功能转换为 ES5

在本章中,我们将学习如何将 ES7 功能转换为 ES5。

ECMA Script 7 添加了以下新功能 −

  • Async-Await
  • 指数运算符
  • Array.prototype.includes()

我们将使用 babeljs 将它们编译为 ES5。根据您的项目要求,也可以在任何 ecma 版本中编译代码,即 ES7 到 ES6 或 ES7 到 ES5。由于 ES5 版本最稳定,可以在所有现代和旧浏览器上正常运行,因此我们将代码编译为 ES5。

Async-Await

Async 是一个异步函数,它返回一个隐式承诺。承诺要么被解决,要么被拒绝。异步函数与普通标准函数相同。该函数可以有 await 表达式,该表达式会暂停执行,直到它返回承诺,一旦它得到承诺,执行就会继续。只有当函数是异步时,Await 才会起作用。

这是一个关于 async 和 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

在调用计时器函数之前添加 await 表达式。计时器函数将在 5 秒后返回承诺。因此,await 将暂停执行,直到计时器函数上的承诺得到解决或拒绝,然后继续。

现在让我们使用 babel 将上述代码转换为 ES5。

ES7 - Async-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();

命令

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 不编译对象或方法;因此这里使用的承诺将不会被转译,并将按原样显示。为了在旧浏览器上支持承诺,我们需要添加支持承诺的代码。现在,让我们按如下方式安装 babel-polyfill −

npm install --save babel-polyfill

它应该保存为依赖项而不是 dev-dependency。

要在浏览器中运行代码,我们将使用 node_modules\babel-polyfill\dist\polyfill.min.js 中的 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="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 - String Padding

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 编译流程涉及以下 3 个部分 −

  • parsing
  • transforming
  • printing

提供给 babel 的代码会按原样返回,只是语法有所改变。我们已经看到预设被添加到 .babelrc 文件中,以将代码从 es6 编译为 es5 或反之亦然。预设只不过是一组插件。如果在编译期间未提供预设或插件详细信息,Babel 将不会更改任何内容。

现在让我们讨论以下插件 −

  • transform-class-properties
  • Transform-exponentiation-operator
  • For-of
  • object rest and spread
  • async/await

现在,我们将创建一个项目设置并处理一些插件,这将清楚地了解 babel 中插件的要求。

命令

npm init

我们必须安装 babel 所需的软件包 - babel cli、babel core、babel-preset 等。

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;

In ES6, class syntax is as follows

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

将插件添加到 babel 6 的 .babelrc 文件中

Add Plugin Babelrc

babel 7 的 .babelrc

{
    "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 输出

指数运算符 - 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 输出

For-of

babel6、7 中插件所需的包如下 −

Babel6

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

Babel 7

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

.babelrc for babel6

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

.babelrc for babel7

{
   "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 输出

object rest spread

babel6 和 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 babel6

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

.babelrc for babel7

{
   "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 来实现相同的功能,因为它在不支持承诺的浏览器中无法工作。

输出

Async es5 output

BabelJS - Babel Polyfill

Babel Polyfill 为 Web 浏览器添加了对不可用功能的支持。Babel 将代码从最近的 ecma 版本编译为我们想要的版本。它根据预设更改语法,但无法对使用的对象或方法执行任何操作。我们必须对这些功能使用 polyfill 以实现向后兼容。

可以 polyfill 的功能

以下是在旧版浏览器中使用时需要 polyfill 支持的功能列表 −

  • Promises
  • 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。

babel 6 的 .babelrc

Babelrc

babel 7 的 .babelrc

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

我们将安装一个 lite-serve,以便我们可以在浏览器中测试我们的代码 −

npm install --save-dev lite-server

让我们添加 babel 命令以在 package.json 中编译我们的代码 −

Babel Command

我们还添加了调用 lite-server 的 build 命令。

Babel-polyfill 与 babel-core 包一起安装。babel-polyfill 将在节点模块中可用,如下所示 −

Node Modules

我们将进一步研究承诺并与其一起使用 babel-polyfill。

ES6 - Promises

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。要在浏览器中运行代码,我们将从节点模块中获取 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>

注意 −在主 javascript 调用之前,必须在开始时使用 Polyfill 文件。

字符串填充

字符串填充根据指定的长度从左侧添加另一个字符串。字符串填充的语法如下所示 −

语法

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 示例
m.set("0","A");
m.set("1","B");
console.log(m);

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

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

let wm = new WeakMap(); //weakmap 示例
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 示例
m.set("0", "A");
m.set("1", "B");
console.log(m);

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

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

var wm = new WeakMap(); //weakmap 示例
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 脚本。我们将在本章中讨论这些命令的使用。

首先,我们将为我们的项目安装 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

显示

安装包

我们已经安装了 babel-cli,这里是更新后的 package.json −

更新后的包

除此之外,我们还需要安装 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 local。为了在我们的项目中使用 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

输出

更新文件输出

您可以对主文件进行更改;此更改将反映在编译文件中。

在上述情况下,我们更改了日志消息,并且 --watch 选项会不断检查是否有任何更改,并将相同的更改添加到编译文件中。

更改主文件

编译文件

编译文件

在前面的部分中,我们学习了如何编译单个文件。现在,我们将编译一个目录,并将编译后的文件存放在另一个目录中。

在src文件夹中,我们将再创建一个名为main1.js的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-transpiler 的配置详细信息,用于指示其以指定模式进行转译。以下是我们将在本章中讨论的一些最流行的预设 −

  • ES2015
  • Env
  • React

我们需要使用具有我们希望代码转换的环境的预设。例如,es2015 预设将代码转换为 es5。值为 env 的预设也将转换为 es5。它还有附加功能,即选项。如果您希望该功能在较新版本的浏览器上得到支持,那么只有当这些浏览器不支持该功能时,babel 才会转换代码。使用 Preset react,Babel 会在需要 react 时转换代码。

要使用 Preset,我们需要在项目根文件夹中创建 .babelrc 文件。为了展示工作原理,我们将创建一个项目设置,如下所示。

命令

npm init
Work Preset

我们必须安装所需的 babel 预设,如下所示,以及 babel cli、babel core 等。

Babel 6 packages

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 7 开始,babel-preset-es2015 已弃用。

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 中的脚本部分添加了 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 preset,你可以指定最终代码要转译到的环境。

我们将使用上面创建的相同项目设置,并将预设从 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 的最后一个版本,如下所示。

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 负责根据环境编译代码。我们还可以根据 nodejs 环境定位编译,如下所示

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 根据当前版本的 nodejs 编译代码。

React Preset

在使用 Reactjs 时,我们可以使用 react preset。我们将进行一个简单的示例,并使用 react preset 查看输出。

要使用 preset,我们需要安装 babel-preset-react (babel 6),如下所示 −

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

对于 babel 7,如下所示 −

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

对于 babel6,对 .babelrc 的更改如下 −

Change Babelrc

For 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!"
);

使用 preset:react 将 main.js 中的代码转换为 reactjs 语法。

BabelJS - 使用 Babel 和 Webpack

Webpack 是一个模块打包器,它将所有带有依赖项的模块(js、样式、图像等)打包到静态资产 .js、.css、.jpg、.png 等中。Webpack 附带预设,可帮助编译成所需的形式。例如,react 预设有助于以 react 形式获取最终输出,es2015 或 env 预设有助于以 ES5 或 6 或 7 编译代码等。我们在项目设置中使用了 babel 6。如果您想切换到 babel7,请使用 @babel/babel-package-name 安装所需的 babel 包。

在这里,我们将讨论使用 babel 和 webpack 进行项目设置。创建一个名为 的文件夹,并在 Visual Studio IDE 中打开它。

要创建项目设置,请按如下方式运行 npm initbabelwebpack −

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 −

安装后的软件包

现在,我们将创建一个 webpack.config.js 文件,其中包含捆绑 js 文件的所有详细信息。这些文件将使用 babel 编译为 es5。

要使用服务器运行 webpack,我们使用 webpack-server。以下是添加到其中的详细信息 −

Webpack Server

我们添加了发布命令,它将启动 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']
            }
         }
      ]
   }
};

文件的结构如上所示。它以路径 h 开头,提供当前路径详细信息。

var path = require('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'
},

输出是一个包含路径和文件名详细信息的对象。路径将保存编译文件所在的文件夹,文件名将告诉您 .html 文件中使用的最终文件的名称。

模块

module: {
   rules: [
      {
         test: /\.js$/,
         include: path.resolve(__dirname, 'src'),
         loader: 'babel-loader',
         query: {
            presets: ['env']
         }
      }
   ]
}
  • 模块是包含规则细节的对象。它具有以下属性 −

    • test
    • include
    • loader
    • query
  • Test 将保存所有以 .js 结尾的 js 文件的详细信息。它具有模式,将在给定的入口点末尾查找 .js。

  • Include 指示要查看的文件上使用的文件夹。

  • Loader 使用 babel-loader 编译代码。

  • Query 具有属性 presets,它是一个值为 env – es5 或 es6 或 es7 的数组。

在其中创建文件夹 src 和 main.js;使用 ES6 编写您的 js 代码。稍后,运行该命令以查看它是否使用 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

要检查输出,我们可以在 −

http://localhost: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 是一种结合了 xml 语法的 JavaScript 代码。JSX 标签具有标签名称、属性和子元素,使其看起来像 xml。

React 使用 JSX 进行模板化,而不是常规 JavaScript。它不是必须使用的,但是它具有以下优点。

  • 它速度更快,因为它在将代码编译为 JavaScript 时执行优化。

  • 它也是类型安全的,大多数错误都可以在编译期间捕获。

  • 如果您熟悉 HTML,它可以更轻松、更快地编写模板。

我们在项目设置中使用了 babel 6。如果您想要切换到 babel 7,请使用 @babel/babel-package-name 安装所需的 babel 软件包。

我们将创建项目设置并使用 webpack 使用 Babel 将带有 react 的 jsx 编译为普通 JavaScript。

要启动项目设置,请运行下面给出的 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']
            }
         }
      ]
   }
};

文件的结构如上所示。它以路径开始,提供当前路径详细信息。

var path = require('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'
},

输出是一个包含路径和文件名详细信息的对象。路径将保存编译文件的文件夹,文件名将告诉您在 .html 文件中使用的最终文件的名称。

模块

module: {
   rules: [
      {
         test:/\.(js|jsx)$/,
         include: path.resolve(__dirname, 'src'),
         loader: 'babel-loader',
         query: {
            presets: ['es2015','react']
         }
      }
   ]
}
  • Module 是具有规则详细信息的对象,其具有属性,即 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 并添加预设,如下所示

添加预设

创建 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 包名称。

我们创建了一个名为 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
安装 Gulp

我们将向 .babelrc 文件添加预设环境详细信息,如下所示

预设环境详细信息

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

We have created three task in gulp, ['build','watch','connect']. All the js files available in src folder will be converted to es5 using babel as follows −

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

我们在 gulp 中创建了三个任务,['build','watch','connect']。src 文件夹中的所有 js 文件都将使用 babel 转换为 es5,如下所示

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

这是使用 transpiled 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 环境详细信息

由于我们需要 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 项目结构

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 以构建最终文件。

最终项目结构如下所示 −

最终项目结构

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

编译后的代码在所有浏览器中均可正常运行。