带你重学ES6 | Export(谨记输出的都是变量)

在原始的 JS 时代,是没有模块化的概念的,随着前端项目的愈来愈大,而且前端的地位愈来愈主要,急需模块化的概念引入进来。在 ES6 以前,社区制定了一些模块化的方案,如:CommonJS 和 AMD。ES6 以后这两个正在慢慢的被 import 和 export 所取代。前端

这让我想起了以前面试的时候一个面试官问我 ES6 为何要引入 import 和 export,个人回答是为了模块化的加载,避免全局污染,而后他问了一个让我至今难忘的问题,为何是 import 和 export 这两个单词????😓😓😓 当时的我顿时语塞,只能弱弱的回答一句,JS 规范的....git

一、export

export 用于规定模块对外的接口,无论你是否认义,export 导出的模块都是处于严格模式,不能用在嵌入式脚本中。github

export 导出的语法有两种:面试

  1. 命名导出(每一个模块包含任意数量)
  2. 默认导出(每一个模块只包含一个)

1.一、命名导出

如在 a.js 文件中,想要导出几个变量,咱们能够写成以下两种形式。编程

// a.js
// 第一种
export var a = 1;
export var b = 2;
export var c = 3;
// 第二种
var a = 1;
var b = 2;
var c = 3;
export { a, b, c };
复制代码

以上两种形式是等价的,可是倾向于第二种写法,由于第二种写法便于阅读,能一眼看出要导出的变量是什么。api

除了能导出变量,咱们在开发中应用最多的就是导出函数和类。markdown

export function foo(a, b{
  return a + b;
}
// 等价于
function foo(a, b{
  return a + b;
}
export { foo };
// 应用到箭头函数
const foo = (a, b) => a + b;
export { foo };
复制代码

导出的名称除了能够是该变量本来的名称外,还能够经过 as 关键词对其重命名。app

var a = 1;
export { a as b, a as c };
复制代码

上述经过 as 关键词对 a 变量进行了重命名,而且同一个变量能够重命名屡次。模块化

有一点值得注意的是,export 输出的必定是一个变量,变量,变量,重要的事情说三遍。函数

// 第一种
export 1// 报错
// 第二种
var a = 1;
export a; // 报错
复制代码

上述两种导出接口的方式均报错,由于输出均不是变量,第二种虽然 a 是变量,可是实际上跟第一种是同样的,只是变换了一下写法,函数和类也是如此。

1.二、默认导出

咱们能够经过 export default 命名对模块进行默认导出,而且一个模块中只能有一个默认导出。

export default function (a, b{
  return a + b;
}

export default function foo(a, b{
  return a + b;
}

export default 1;

var a = 1;
export default a;
复制代码

上一节咱们说 export 最重要的是导出的接口是变量,在默认导出中发现若是导出的不是变量的话也是能够的,这是由于 default 其实就是一个变量,因此能够导出的不是一个变量,可是 default 后面跟着的是一个变量话,会报错。

export default var a = 1// 报错
复制代码

二、import

import 命令用于输入其余模块提供的功能。export 有两种语法形式,对应的 import 也有两种语法形式

2.一、当输出是用的 export 语法时

// a.js
var a = 1;
var b = 2;
export { a, b };

import { a, b } from "a.js";
复制代码

当 export 输出模块接口时,import 要用大括号来进行导入,默认状况下导入的名称要和输出的名称一致。若是想要更改导入的名称,咱们一样能够用 as 关键词进行重命名。

// a.js
var a = 1;
var b = 2;
export { a, b };

import { a as a1, b as b1 } from "a.js";
复制代码

2.二、当输出是用的 export default 语法时

// a.js
var a = 1;
export default a;

import a from "a.js";
复制代码

也能够和上一节一块使用:

// a.js
var a = 1;
var b = 2;
var c = 3;
export default c;
export { a, b };

import c, { a, b } from "a.js";
复制代码

2.三、import 的其余特性

import 表达式引入进来的全部模块都是只读形式,也就是说,不容许在加载模块的脚本里面,改写模块。

import { a } from "a.js";

a = {}; // Syntax Error : 'a' is read-only;
复制代码

可是若是引入的模块是一个对象类型的话,它的属性是能够更改。

import { a } from "a.js";
a.name = "Jack"// 合法
复制代码

虽然说此功能合法,可是在实际开发中仍是要慎用。

import 后面的 from 指定模块文件的位置,能够是相对路径,也能够是绝对路径,.js 后缀能够省略。若是只是模块名,不带有路径,那么必须有配置文件,告诉 JavaScript 引擎该模块的位置。

import { myMethod } from "util";
复制代码

上面代码中,util 是模块文件名,因为不带有路径,必须经过配置,告诉引擎怎么取到这个模块。

import 还有一个特性时,import 具备提高,会提高到整个文件的最顶端,首先执行。

foo(); // 不会报错
import { foo } from "a.js";
复制代码

上述例子不会报错的缘由就是由于 import 具备提高,提高到了 foo()以前,首先执行。

除此以外,import 不能当作表达式和变量,不能参与运算。

import {'1' + foo} from 'a.js' // 报错
// 报错
if (x === 1) {
  import { foo } from 'module1';
else {
  import { foo } from 'module2';
}
复制代码

import 还能够仅仅导入模块,但不作任何的输入。

import "a.js";
复制代码

这将运行模块中的全局代码, 但实际上不导入任何值。

与上述相反的是,将模块所有导入,总体加载,而且一样支持经过 as 关键词重命名。

import * from 'a.js'

import * as b from 'a.js'
复制代码

2.四、export 和 import 复合写法

若是在一个模块中先输入后输出同一个模块,那能够运用 export 和 import 复合写法,即 export...from...

export { foo, bar } from "a.js";
// 能够简单的理解为
import { foo, bar } from "a.js";
export { foo, bar };
复制代码

值得注意的是,上述的 foo 和 bar 并无引入到当前模块,当前模块至关于一个中转站,只是对 foo 和 bar 进行转发。

一样咱们依然能够对转发的模块进行重命名,并且能够经过*对其所有转发。

export { foo as foo1 } from "a.js";
export * from "a.js";
复制代码

在 ES2020 中还能够对*经过 as 关键词进行重命名。

export * as a from "a.js";
// 等价于
import * as a from "a.js";
export { a };
复制代码

除此以外,在 export 和 import 复合写法中,咱们能够对默认模块进行转发。

export { default } from "a.js";
复制代码

是否是感受很奇怪,没错,我第一次见到的时候也很奇怪,可是后期想了一下,export...from...导入变量,default 也是变量的一种,因此这种也就不奇怪了。

依旧能够经过 as 进行重命名。

export { default as foo } from "a.js";
复制代码

而且还能够将具名接口改成默认接口。

export { foo as default } from "a.js";
// 等价于
import { foo } from "a.js";
export default foo;
复制代码

2.五、import()

ES2020 中新增了 import(),主要是为了解决没法动态导入的问题,由于以前也说过,JS 为了静态分析优化,因此 import 必须放在整个模块的顶部,而且不能和表达式混合使用,这在有些场景,尤为是 Node 中非常麻烦,这也是为何 Node 仍是偏向用 require 导入接口的缘由之一。

使用 import()动态加载接口的用法很简单,括号内填写要动态导入接口就能够。

import("a.js");
复制代码

import()会返回一个 Promise 对象。

import("a.js").then((value) => console.log(value));
复制代码

import()的应用,最直观的就是应用在动态加载组件上,咱们能够看到 dva 中dva/dynamic其内部主要就是运用了 import(),对组件和路由进行动态加载,达到优化目的。

import dynamic from "dva/dynamic";

const UserPageComponent = dynamic({
  app,
  models() => [import("./models/users")],
  component() => import("./routes/UserPage"),
});
复制代码

这次也是对export和import有了个从新的认识,也但愿对你有所帮助。 点个赞吧!💥🧡💖

后语

以为还能够的,麻烦走的时候能给点个赞,你们一块儿学习和探讨!

还能够关注个人博客但愿能给个人github上点个Start,小伙伴们必定会发现一个问题,个人全部用户名几乎都与番茄有关,由于我真的很喜欢吃番茄❤️!!!

想跟车不迷路的小伙还但愿能够关注公众号 前端老番茄 或者扫一扫下面的二维码👇👇👇。

我是一个编程界的小学生,您的鼓励是我不断前进的动力,😄但愿能一块儿加油前进。

本文使用 mdnice 排版

相关文章
相关标签/搜索