彻底掌握ES6的Module语法

1,835 阅读5分钟

「这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战

前言

前段时间进行代码质量巡检的时候,忽然报错模块不存在。经过代码排查发现,竟然是模块的导出和引入方式不匹配导致的。纳尼?难道ES Module不是日常开发必备技能吗?这必须得整篇文章给它掰扯的明明白白的。当然了,如果您对ES Module的api已经了如指掌的话,其实往下看就没有什么太多干货了。

ES Module是啥玩意

ES Module是ES6中提出的一个新的模块加载方式。在我看来,ES Module的最大好处就是取代commonJs和AMD两种模块加载方式,实现服务端和浏览器端模块加载的大一统。当然,ES Module在资源加载速度和静态分析方面也是好处大大的,不过暂时不在我们目前的考虑范围内。

ES Module秘籍

export 语法

1. export + 变量声明

这种方式应该是大家日常开发中使用频率最高的的一种接口导出方式,尤其是在封装公共方法或者抽取业务模块的时候。

但是这里还是需要罗嗦一下,这种方式的语法规范是 export + 变量声明(var、const和let都可以),但是不支持 export 后面直接使用变量名称。

    // 正确使用方式
    export const moduleName = "es module";

    export const moduleType = "js";

    export const moduleSize = 200;

    // 错误使用方式
    export moduleName;

    const moduleType = "js";

    export moduleType;

需要特别注意的是,export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系

2. export + {}

这种接口导出的方式,说穿了就是在模块进行大量的逻辑的铺排,然后再模块的底部将需要对外开放的接口一次性导出即可。

不知道大家的使用情况,但是就我个人而言,这种导出接口的方式在日常开发中可能使用频率不是很高。不过,我在很多第三方库的源码中还是会经常看到它们的身影。悄悄的讲,这种导出方式其实是官方推荐优先使用的一种方式。这种写法最大的好处就是可读性高,可以在模块的底部快速的找到对外导出的接口,然后按需导入想要使用的接口。

    const moduleName = "es module";

    const moduleType = "js";

    const moduleSize = 200;

    export {
      moduleName,
      moduleType,
      moduleSize,
    }

3. export default

相信只要对ES Module有所了解的小伙伴们都应该知道这个api吧。无论是使用React,还是使用Vue都会大量的使用这个api。

我对于这个api的理解,其实就是前面第2个语法的语法糖,相当于进行了 export { * as default },这里我们先记下即可,后面我们讲到import的时候结合起来一起看一下。

    const moduleInfo = {
      name: 'es module',
      type: 'js',
      size: 200,
    }

    export default moduleInfo;

import 语法

1. import 普通接口

针对export中的前两种接口导出方式,import有与之对应的接口引入方式。这种接口引入的方式的语法是:import { [name] } from '[moduleName]',其中name对应export的接口名称,moduleName的模块名称或者模块路径。

这里我还是要唠叨两句,通过export { [name] }导出的接口,不支持通过import [name]的方式导入。

    // 正确使用方式
    import { moduleName, moduleType, moduleSize } from './modules/index';

    // 错误使用方式
    import module from './modules/index';

2. import default接口

针对export default [name]导出的接口也有一套与之匹配的接口导入方式。比较常规的导入方式是通过 import [name]的方式引入,这也是我们日常开发中使用最高频的导入方式。

    // 正确使用方式
    import module from './modules/index';

    // 错误使用方式
    import { module } from './modules/index';

当然,其实还是有其它的奇淫巧计可以导入的。这里我们先回忆一下前面说的,export default其实是export { * as default },如果成立的话,我们其实也可以通过 import 普通接口的方式将其导入。(经过验证其实是完全可行的哈)。

    import { default as module } from './modules/index';

3. import *

说实话,在不考虑代码tree shake的前提条件下,其实是蛮省事情的,但是如果考虑到tree shake的话,我目前没有想象到什么比较好的应用场景。

    import * as module from './modules/index';

export 和 import 的组合拳

不得不佩服大佬们的实力哈,不过可以单独使用export和import,还可以将它们组合起来一起使用,组合起来不仅更加便捷,而且更加牛皮。说实话,我第一次在源码中见到这种写法的时候,第一反应是这是什么玩意,百度了一下,就立马跳起来了,我擦,这玩意也太牛皮了吧,还能这么写?

    export * from './modules/index'

这段代码看着削微有点难以理解,其实就是下面这段代码的变种:

    import * as index from './modules/index';
    export { ...index }

看到这里,我忍不住就想玩几个花活。

    // 花活一
    export { default as help } from './help';

    // 花活二
    export { cancel as default } from './help'; 

其实就是为了花活而花活,感觉后面这两个没什么实际应用场景。

结尾

看完这篇文章,是不是对ES Module的api有了比较深入的了解,想必迫不及待地去试上一试了吧?别急,先点赞关注评论三连,然后再去一展拳脚吧。

欢迎小伙伴们进行交流哟。