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://babel.node.org.cn/

Compiler

BabelJS - 环境搭建

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

要使用 BabelJS,我们需要以下设置 -

  • NodeJS
  • Npm
  • Babel-CLI
  • Babel-Preset
  • 用于编写代码的 IDE

NodeJS

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

Nodejs

如果它没有打印任何内容,请在您的系统上安装 nodejs。要安装 nodejs,请访问 nodejs 的主页 https://node.org.cn/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://127.0.0.1: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

编译后的代码在所有浏览器中都能正常工作。

广告