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 脚本的下一版本)。现在还不确定什么时候所有浏览器能够兼容所有发布的 ES 版本。

如果我们计划使用 ES6 或 ES7 或 ES8 功能来编写代码,由于缺乏对新更改的支持,它往往会在某些旧浏览器中崩溃。因此,如果我们想在代码中使用 ECMA Script 的新功能,并希望在所有可用的浏览器上运行它,我们需要一个工具来编译 ES5 中的最终代码。

Babel也做了同样的事情,它被称为转译器,可以将代码转译为我们想要的 ECMA 脚本版本。它具有预设和插件等功能,可配置我们转换代码所需的 ECMA 版本。借助 Babel,开发人员可以使用 JavaScript 中的新功能编写代码。用户可以使用 Babel 来转译代码;这些代码稍后可以在任何浏览器中使用,没有任何问题。

下表列出了 ES6、ES7 和 ES8 中可用的功能 -

特征 ECMA 脚本版本
让 + 常量 ES6
箭头功能 ES6
课程 ES6
承诺 ES6
发电机 ES6
迭代器 ES6
模块 ES6
解构 ES6
模板文字 ES6
增强对象 ES6
默认、剩余和传播属性 ES6
异步 - 等待 ES7
求幂运算符 ES7
Array.prototype.includes() ES7
字符串填充 ES8

BabelJS 管理以下两部分 -

  • 转译
  • 聚填充

什么是 Babel 转译器?

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

什么是 Babel-polyfill?

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

以下是 JavaScript 中可用的 ECMA 脚本功能列表,可以对其进行转译和填充 -

  • 课程
  • 装饰器
  • 常量
  • 模块
  • 破坏
  • 默认参数
  • 计算属性名称
  • 物体静止/展开
  • 异步函数
  • 箭头功能
  • 其余参数
  • 传播
  • 模板文字

可以进行多填充的 ECMA 脚本功能 -

  • 承诺
  • 地图
  • 象征
  • 弱图
  • 弱集
  • 包括
  • Array.from、Array.of、Array#find、Array.buffer、Array#findIndex
  • 对象.分配、对象.条目、对象.值

BabelJS 的特点

在本节中,我们将了解 BabelJS 的不同功能。以下是 BabelJS 最重要的核心功能 -

Babel 插件

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

Babel-预设

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

Babel-Polyfills

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

Babel-Polyfills

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

使用 BabelJS 的优点

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

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

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

  • BabelJS 可以与 gulp、webpack、flow、react、typescript 等一起使用,使其非常强大,可以与大型项目一起使用,使开发人员的生活变得轻松。

  • BabelJS 还可以与 React JSX 语法一起工作,并且可以以 JSX 形式编译。

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

使用 BabelJS 的缺点

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

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

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

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

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

编译器

BabelJS - 环境设置

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

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

  • NodeJS
  • 尼普
  • Babel-CLI
  • Babel-预设
  • 用于编写代码的 IDE

NodeJS

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

Nodejs

如果它没有打印任何内容,请在您的系统上安装nodejs。要安装nodejs,请进入nodejs主页https://nodejs.org/en/download/,根据您的操作系统安装软件包。

以下截图显示了nodejs的下载页面 -

下载

根据您的操作系统,安装所需的软件包。一旦安装了nodejs,npm也会随之安装。要检查 npm 是否已安装,请在终端中输入npm –v 。它应该显示 npm 的版本。

命令

BabelJS-CLI

Babel 带有内置的命令行界面,可用于编译代码。

创建一个您将在其中工作的目录。在这里,我们创建了名为babelproject的目录。让我们使用nodejs 来创建项目详细信息。

我们使用npm init创建项目,如下所示 -

Npm 初始化

这是我们创建的项目结构。

项目结构

现在要使用 Babel,我们需要安装 Babel cli、Babel 预设、Babel 核心,如下所示 -

babel-cli

执行以下命令安装 babel-cli -

npm install --save-dev babel-cli

巴别尔Cli

babel 预设

执行以下命令安装 babel-preset -

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

通天塔预设

babel 核心

执行以下命令来安装 babel-core -

npm install --save-dev babel-core

巴别塔核心

安装后,以下是 package.json 中提供的详细信息 -

我们已经在项目本地安装了 babel 插件。这样做是为了我们可以根据项目需求以及不同版本的 babeljs 在我们的项目中以不同的方式使用 babel。Package.json 给出了所使用的 babeljs 的版本详细信息。

为了在我们的项目中使用 babel,我们需要在 package.json 中指定相同的内容,如下所示 -

封装Json

Babel主要用于编译JavaScript代码,它将具有向后兼容性。现在,我们将在 ES6 -> ES5 或 ES7 -> ES5 以及 ES7->ES6 等中编写代码。

为了在执行时向 Babel 提供相同的指令,我们需要在根文件夹中创建一个名为 .babelrc 的文件。它包含一个 json 对象,其中包含预设的详细信息,如下所示 -

Json对象

我们将创建 JavaScript 文件 index.js 并使用 Babel 将其编译为 es2015。在此之前,我们需要安装 es2015 预设,如下所示 -

安装es2015

在index.js中,我们使用箭头函数创建了一个函数,这是es6中添加的新功能。使用 Babel,我们将代码编译为 es5。

Js_索引

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

npx babel index.js

输出

es2015输出

它显示了 es5 中的 index.js 代码,如上所示。

我们可以通过执行命令将输出存储在文件中,如下所示 -

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

输出

执行

这是我们创建的文件,index_es5.js -

创建索引

BabelJS - ES6 代码执行

BabelJS是一个 JavaScript 转译器,它将 JavaScript 中添加的新功能转换为 ES5 或根据给定的预设或插件做出反应。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>

索引.js 文件

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

alert(_foo());

输出

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

Chrome浏览器

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

产生

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

IE浏览器

我们已经使用了ES6的Arrow函数;如上所示,这并不适用于所有浏览器。为了实现这一点,我们使用 BabelJS 将代码编译为 ES5 并在所有浏览器中使用它。

将使用 babeljs 将 js 文件编译为 es5 并在浏览器中再次检查。

编译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>

索引_new.js

"use strict";

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

alert(_foo());

镀铬输出

镀铬输出

火狐浏览器输出

火狐浏览器输出

IE浏览器输出

IE浏览器输出

BabelJS - 使用 Babel 6 进行项目设置

在本章中,我们将看到如何在我们的项目中使用 babeljs。我们将使用nodejs创建一个项目并使用http本地服务器来测试我们的项目。

创建项目设置

在本节中,我们将学习如何创建项目设置。

创建一个新目录并运行以下命令来创建项目 -

npm init

输出

执行后,上述命令会生成以下输出 -

Npm 初始化输出

以下是创建的 package.json -

包 Json 创建

我们将安装开始使用 babeljs 所需的软件包。我们将执行以下命令来安装babel-cli、babel-core、babel-preset-es2015

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

输出

执行后,上述命令会生成以下输出 -

Npm 安装输出

Package.json 更新如下 -

包 Json 更新

我们需要http服务器来测试js文件。执行以下命令安装 http 服务器 -

npm install lite-server --save-dev

我们在 package.json 中添加了以下详细信息 -

安装http服务器

在脚本中,Babel 负责从src文件夹转译 script.js 并将其保存在名为script.bundle.js的dev文件夹中。我们在 package.json 中添加了完整的命令来编译我们想要的代码。此外,还添加了构建,这将启动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

呼叫巴别塔

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 通用运行

输出

上述命令生成以下输出 -

Npm 通用运行输出

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 进行 pacakge 安装。

babel 7 中已弃用了一些预设。列表如下 -

  • ES20xx 预设
  • babel-预设-env
  • babel-预设-最新
  • 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文件并以打字稿形式编写代码 -

测试.ts

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

getName("Siya");

.babelrc

Babelrc 打字稿

命令

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

测试.js

"use strict";

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

getName("Siya");

BabelJS - 将 ES6 功能转换为 ES5

在本章中,我们将看到 ES6 中添加的功能。我们还将学习如何使用 BabelJS 将功能编译为 ES5。

以下是我们将在本章中讨论的各种 ES6 功能 -

  • 让 + 常量
  • 箭头功能
  • 课程
  • 承诺
  • 发电机
  • 解构
  • 迭代器
  • 模板文字
  • 增强对象
  • 默认、剩余和传播属性

让 + 常量

Let 在 JavaScript 中声明一个块作用域局部变量。请考虑以下示例以了解 let 的用法。

例子

let a = 1;
if (a == 1) {
   let a = 2;
   console.log(a);
}
console.log(a);

输出

2
1

第一个控制台打印 2 的原因是因为a再次使用let声明,并且仅在if块中可用。使用 let 声明的任何变量仅在声明的块中可用。我们使用let声明了变量a两次,但它并没有覆盖a的值。

这就是 var 和 let 关键字之间的区别。当您使用 var 声明变量时,该变量将在函数范围内可用,或者如果声明则将充当全局变量。

如果使用 let 声明变量,则该变量在块作用域内可用。如果在 if 语句内声明,则它仅在 if 块内可用。这同样适用于 switch、for 循环等。

我们现在将看到使用 babeljs 在 ES5 中进行代码转换。

让我们运行以下命令来转换代码 -

npx babel let.js --out-file let_es5.js

let 关键字从 es6 到 es5 的输出如下 -

让我们使用ES6

let 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 关键字。

例子

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 附带了新的 Classes 功能。类类似于 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;

承诺

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

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

承诺有三种状态 -

  • 待定(初始状态)
  • 已解决(成功完成)
  • 被拒绝(失败)

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

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

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

以下代码行显示了 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 - 承诺

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*,其中 * 表示函数,并且在函数内部使用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}

输出给出一个具有值的对象,并作为属性完成。每个next()方法调用都会给出数组中的下一个值,并以 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 填充

解构

解构属性的Behave类似于 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,我们可以使用函数 params 的默认参数,如下所示 -

例子

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

在上面的函数中,我们将 n 个参数传递给函数 add。如果是在 ES5 中,要添加所有这些参数,我们必须依靠参数对象来获取参数的详细信息。在 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

通天塔-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属性也有像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

巴别塔-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));

代理

代理是一个对象,您可以在其中定义属性查找、赋值、枚举、函数、调用等操作的自定义Behave。

句法

var a = new Proxy(target, handler);

目标和处理程序都是对象。

  • target是一个对象,也可以是另一个代理元素。

  • handler将是一个对象,其属性作为函数,在调用时将给出Behave。

让我们尝试借助示例来理解这些功能 -

例子

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

巴别塔-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 代码模块中的函数或变量不可用,除非模块文件导出它们。

简而言之,模块可帮助您在模块中编写代码,并仅公开应由代码其他部分访问的代码部分。

让我们考虑一个示例来了解如何使用模块以及如何导出它以在代码中使用它。

例子

添加.js

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

module.exports=add;

乘法.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.jsmultip.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

包.json

ES6 模块 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 运行包

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 运行发布

在您的项目中添加index.html。这将调用 dev/main_bundle.js。

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

输出

主捆绑包

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

后

现在让我们创建 gulpfile.js,它将帮助运行将模块捆绑在一起的任务。我们将使用上面与 webpack 相同的文件。

例子

添加.js

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

module.exports=add;

乘法.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 是在此处创建的。用户将 browserfiy 并使用 tranform 来 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,其中使用预设 env 调用 babelify。

带有 main.js 的 src 文件夹被提供给 browserify 并保存在 dev 文件夹中。

我们需要运行命令gulp start来编译文件 -

命令

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