ES6: import和export

2023-05-16

模块化

前端模块化的好处都已经被说烂了,归纳为两点:

  1. 避免全局变量污染
  2. 有效的处理依赖关系

ES2015(ES6)终于引入了模块的概念,最近学习了下,顺便记下笔记。

准备工作

借助Babel演示Demo。
创建个module目录,并在该目录里执行:

npm init -y

然后安装各种依赖:

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

接着创建.babelrc文件:

{
  "presets": [
      "es2015",
      "env"
      ]
}

修改package.json文件的"scripts"配置:

"scripts": {
    "build": "babel src --out-dir dist"
  }

最终的目录结构如:

clipboard.png

模块导出

一个文件定义一个模块,通过export语句导出该模块输出的变量。export语句有两种语法格式:命名导出默认导出

1 命名导出

命名导出就是显示指定导出变量的名称。
在src目录下创建math.js,index.js文件。
math.js内容:

// Case 1: export后面跟变量输出声明语句
var PI = 3.14;
export { PI }; // 导出变量PI,花括号不可省略

// Case 2: export后面直接跟变量定义语句
export var add = function (x, y) { // 导出函数print
    return x + y;
}

这表示math.js模块导出变量PI和add, 用NodeJS的模块格式可表示为:

var PI = 3.14;
var add = function (x, y) { // 导出函数print
    return x + y;
}

module.exports.PI = PI; 
module.exports.add = add;

index.js内容:

import * as Math from "./math.js"; // import是导入模块,后面会说。

console.log(Math.PI);
console.log(Math.add(1, 2));

然后执行下面的命令进行Babel转换:

npm run build

如果没有报错的化,那module目录下应该生成了dist子目录,并且生成了index.js和math.js文件(先不要在意文件的内容)。
然后在执行命令:

node dist/index.js

看看输出结果是否OK:

3.14
3

命名导出主要用于输出多个变量,并且export此时后面既可以是变量输出声明语句块,也可以是变量定义语句(如Case 2)。
如果导出多个变量,可以采用简写格式(调整math.js内容):

var PI = 3.14;
var add = function (x, y) { 
    return x + y;
}
export { PI, add }; // 简写格式,统一列出需要输出的变量

重复上述步骤中执行npm和Node命令查看看输出结果是否OK。
并且该简写格式还可以对输出的变量重命名:
再次修改math.js

var PI = 3.14;

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

export { PI, add as Add}; // 把输出变量add重命名为Add(注意不用双引号)

通过关键字as把输出变量add重命名为Add,注意Add是个字面量,不是字符串不需要引号。同样在导入math.js模块的index.js模块也要修改下:

import * as Math from "./math.js";

console.log(Math.PI);
console.log(Math.Add(1, 2)); // Add方法名称改动了。

2 默认导出

通过关键字default修饰export可以指定一个模块的默认输出(在导入模块的默认输出时,不需要指定导出变量名称,这个后面再说)。

// Case 3 常量
export default 25; 

// Case 4 变量
//var PI = 3.14;
//export default PI 

注意
1). default修饰的export后面只能跟表达式(变量,字面量,函数调用等),命名输出的export后面只能跟语句(花括号语句块,变量声明语句);
2). 一个模块最多只能有一个默认导出。

模块导入

通过import语句导入外部模块。对应export语句的两种导出方式(命名模块导出和默认模块导出),import也分别存在两种不同的模块导入语法格式。

1 导入模块的命名输出变量

修改index.js:

import { PI, Add} from './math.js';
console.log(PI);
console.log(Add(1, 2));

表示:导入math.js模块里输出的变量PI, Add,注意名称必须要和math.js模块的输出变量一一对应,否则就是undefined。
重新执行npm和node命令看看输出是否OK。
该格式还支持对导入的变量重命名:

import { PI as pi, Add as add} from './math.js';

如果导入一个模块所有命名输出,可采用通配符"*:
修改index.js:

import * as Math from './math.js'; // 此时必须通过as指定个别名
console.log(Math.PI);
console.log(Math.Add(1, 2));

表示导入模块math.js所有命名输出变量,并通过Math变量引用。

2 导入模块的默认输出

修改math.js:

var PI = 3.14;

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

export { PI, add as Add}; // 简写格式,统一列出需要输出的变量

export default function say() { // 默认输出
    console.log("I am default export");
}

修改index.js:

import say  from "./math.js"; // 
say();

表示导入模块math.js的默认输出,此时不可以用as重命名哦。
执行命令查看输出是否OK。
如果同时导入模块的命名输出和默认输出,可采用格式:

import say, * as Math from './math.js'; 
// OR
import say, { PI, Add } from './math.js'; 

有个限制条件默认导入一定放在命名导入前面,即不能写成:

import * as Math, say from './math.js'; 
// OR
import { PI, Add }, say from './math.js'; 

3 只导入

如果只导入一个模块,但不引用模块的输出变量,可以简写为:

import './math.js'

此时只会出发模块math.js的执行。

修改导入/导出的变量值

1 修改导入的变量值

模块可以导出任何类型变量(引用变量和值变量),如果在模块index.js里修改了模块math.js导出的引用变量或者值变量,那会影响模块math.js里的值么?
修改math.js:

var PI = 3.14;
var Person = {
    name: 'Bob'
}

export { PI, Person}; 
export default function say() {
    console.log(`Person:${JSON.stringify(Person)}, PI:${PI}`)
}

修改index.js:

import say, * as Math from './math.js'; 

say(); // 修改前
Math.Person = 12;
Math.PI = 0;
say(); // 修改后

执行npm和node查看输出:

clipboard.png

从输出可以看出虽然我们在index.js模块里修改了math.js模块的导出变量,但并不会影响math.js里的值。

2 修改导出的变量值

反过来想想,如果模块math.js修改了其导出的引用变量或者值变量在,那会影响模块index.js里的取值么?
修改math.js:

var Count = 0;
var increase =  function() {
    Count++;
}
var Person = {
    name: 'Bob'
}
var changeName = function() {
    Person.name = 'John';
}

export { Count, Person, increase, changeName}; 

修改index.js:

import say, * as Math from './math.js'; 

console.log(`Person:${JSON.stringify(Math.Person)}, Count:${Math.Count}`);// 修改前
Math.increase();
Math.changeName();
console.log(`Person:${JSON.stringify(Math.Person)}, Count:${Math.Count}`);//  修改后

输出:

clipboard.png

从输出可以看出只要math.js修改了导出值就会影响index.js的取值。

3 小结

1). 模块的输出变量(引用类型或者值类型)对其他引用模块来说都是只读的
2). 模块修改了其输出变量的值会影响其他引入模块的取值。

再看export语句

了解了export和import的用法后,我们再看看export语句另一个语法规则:导出引入的模块的变量。上面的例子里export语句都是导出模块自身定义的变量,export还可以导模块引入模块的输出。
在src目录添加文件log.js:

export var Log = function(msg) {
    console.log(msg);
}
export default 'I am log.js';

修改math.js:

var Count = 0;
var increase =  function() {
    Count++;
}
var Person = {
    name: 'Bob'
}

var changeName = function() {
    Person.name = 'John';
}

export { Count, Person, increase, changeName}; 
export default function say() {
    console.log(`Person:${JSON.stringify(Person)}, Count:${Count}`)
}
export * from './log.js'; // 

修改index.js:

import say, * as Math from './math.js'; 

Math.Log('hello'); // 该方法来之log.js模块

查看下输出是否OK。

其中“export * from './log.js';”表示导出模块log.js所有的命名输出。等价于:

export { Log } from './log.js';

注意:这种语法格式“export * from './log.js';”不可以定义别名,而花括号的语法格式“export { Log } from './log.js'”可以定义别名,即:

export { Log as log} from './log.js'

怎么在math.js模块里导出模块log.js的默认输出呢?只能采用先导入,再导出方式:

import logName from './log.js';
export { logName }

参考

  1. MDN export
  2. MDN import
  3. Babel 入门教程
  4. Babel Learn ES2015
  5. An Introduction To JavaScript ES6 Modules
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ES6: import和export 的相关文章

随机推荐

  • 为何float有效位数为7位?

    为何float有效位数为7位 xff1f 首先我们应该明确一点 xff1a C语言中 xff0c xff05 f表示保留7位有效数字7位有效数字 xff1a 是指 整数部分 和小数部分一共7位 单精度数的尾数用23位存储 xff0c 加上默
  • Python绘制正余弦函数图像

    公众号 xff1a Python编程时光 今天打算通过绘制正弦和余弦函数 xff0c 从默认的设置开始 xff0c 一步一步地调整改进 xff0c 让它变得好看 xff0c 变成我们初高中学习过的图象那样 通过这个过程来学习如何进行对图表的
  • JS函数的工厂模式、构造函数模式、原型模式的区别

    创建对象 JS有六种数据数据类型 xff0c 其中五种属于基本数据类型 xff1a Null Boolean undefined String Number 而其它值都是对象 数组是对象 xff0c 函数是对象 xff0c 正则表达式是对象
  • mac 邮件自动归类

    mac 让邮箱自动为你的邮件归类 不知道你的工作当中 xff0c 是否每天会收到一大推的邮件 xff0c 其中对自己有价值的邮件也许也就是这一大推邮件当中的几封邮件 单这几封邮件往往又会被淹没 巧用邮件分类功能 之前使用邮件没有好好的区研究
  • 层次图和HIPO图---描绘软件结构的图形工具

    层次图和HIPO 图 层次图用来描述软件的层次结构 虽然层次图的形式和描绘数据结构的层次方框图相同 xff0c 但是表现的内容却完全不同 层次图中的一个矩形框代表一个模块 xff0c 方框间的连线表示调用关系而不像层次方框图那样表示组成关系
  • continue函数和break函数的区别

    continue函数 谈及contiune函数 xff0c 很多初学者都把它和break弄混淆 xff0c 今天我自己也特意学习了一下 xff0c 在这里分享给大家 当它们用在循环语句的循环体时 xff0c break用于立即退出本层循环
  • linux下进入root用户登录

    1 打开终端 xff0c 输入sudo passwd u root 输入当前用户的登录密码 xff0c 提示如下标红区域信息 解决方案 xff1a 1 xff09 直接输入命令 xff1a su xff0c 输入当前用户登录密码 2 xff
  • 利用Python爬取电影网站

    usr bin env python coding 61 utf 8 39 39 39 本爬虫是用来爬取6V电影网站上的电影资源的一个小脚本程序 xff0c 爬取到的电影链接会通过网页的形式显示出来 39 39 39 import requ
  • python 提取字符串中的数字组成新的字符串

    方法一 有一个字符串text 61 34 aAsmr3idd4bgs7Dlsf9eAF 34 请将text字符串中的数字取出 xff0c 并输出成一个新的字符串 import re text 61 34 aAsmr3idd4bgs7Dlsf
  • Trie树

    转载自http epic 32o cn article asp id 61 47 xff0c 但是这个地址已经不存在了 所以从维基百科拿来个图进行解释 xff1a http zh wikipedia org wiki Trie 今天在vij
  • 【C#学习笔记】读SQL Server2008

    using System using System Data SqlClient namespace ConsoleApplication class Program static void Main string args SqlConn
  • window class, OO

    Wndows中Window Management 的设计 是很符合OO思想 首先每个Window的定义由WNDCLASS结构定义 在WNDCLASS中我们需要给出 Window class name Window的class style 以
  • regex_match

    原型 xff1a bool regex match InputSequence MatchResults Regex Flags 当模式匹配整个输入序列成功时 xff0c 返回的是true 否则返回false 参数说明 1 InputSeq
  • 关于Docker目录挂载的总结

    Docker容器启动的时候 xff0c 如果要挂载宿主机的一个目录 xff0c 可以用 v参数指定 譬如我要启动一个centos容器 xff0c 宿主机的 test目录挂载到容器的 soft目录 xff0c 可通过以下方式指定 xff1a
  • Wireshark网络抓包(一)——数据包、着色规则和提示

    一 数据包详细信息 Packet Details面板内容如下 xff0c 主要用于分析封包的详细信息 帧 xff1a 物理层 链路层 包 xff1a 网络层 段 xff1a 传输层 应用层 1 xff09 Frame 物理层数据帧概况 2
  • FloatingWindow 悬浮窗开源项目总结

    在Android开发中 xff0c 我们不免会遇到悬浮窗展示的需求 xff0c 以下是本人之前star的悬浮窗的开源项目 xff0c 供大家参考 xff1a 一 FloatingWindowDemo 开源项目地址 xff1a https g
  • yum-config-manager的讲解

    问题描述 xff1a yum是RPM的前端程序 xff0c 对于多软件安装时非常好用 xff0c 在虚拟机中想要安装什么软件都可以使用 yum install xff1a 仓库名 命令来快速调用已经安装的仓库里的软件 xff0c 但有时在安
  • 1024与自己做爱做的事情

    1024是什么 xff1f 1024最早起源于一个名为 草榴社区 的论坛 xff0c 该论坛为了防止灌水 xff0c 新用户在论坛内回复与发帖时 xff0c 被限制为 每隔1024秒才可发帖 xff08 回复 xff09 一次 xff0c
  • Nervos CKB 共识协议 NC-Max:突破 Nakamoto Consensus 吞吐量的极限

    带宽实际上是区块链吞吐量的最大限制 xff0c 在美国旧金山举办的 Scaling Bitcoin Meetup 中 xff0c Nervos amp Cryptape 研究员张韧从 带宽利用率 角度分析了诸多共识协议的效率和可行性 Alg
  • ES6: import和export

    模块化 前端模块化的好处都已经被说烂了 xff0c 归纳为两点 xff1a 避免全局变量污染有效的处理依赖关系 ES2015 xff08 ES6 xff09 终于引入了模块的概念 xff0c 最近学习了下 xff0c 顺便记下笔记 准备工作