关于前端的模块化(commonJS、ESmodule)

什么是模块化

  • 模块化开发最终的目的是将程序划分成一个个小的结构
  • 这个结构中编写属于自己的逻辑代码,有自己的作用域,不会影响到其他的结构
  • 这个结构可以将自己希望暴露的变量、函数、对象等导出给其结构使用
  • 上面说提到的结构,就是模块;按照这种结构划分开发程序的过程,就是模块化开发的过程

我着重学习的是ESmodulecommonJS,这也是现在主流使用的模块化开发。

CommonJS
  • Node中对CommonJS进行了支持和实现,在Node中每一个js文件都是一个单独的模块。
  • 模块化的核心就是导入和导出
    • exports和module.exports可以负责对模块中的内容进行导出
    • require函数可以帮助我们导入其他模块(自定义模块、系统模块、第三方库模块)中的内容
  • 细节:exports是一个对象,我们可以在这个对象中添加许多属性
let name = 'xxx'
let age = '18'
function sayhello (){}

exports.name = name;
exports.age= age;
exports.sayhello = sayhello
  • 另一个文件中(假定为main.js)可引入
const bar = require('./bar')
  • CommonJS的理解重点 - 意味着main中的bar变量等于exports对象,即bar变量与exports对象是同一个引用地址。

  • module.exports我们在node中经常用的模块化导出的方法

  • module.exports的引用地址与exports也是一样的,所以:module.exports = exports = main中的bar

  • CJS中的模块在被第一次引入时,模块中的js代码会被运行一次

  • CommonJS规范缺点

    • CommonJS加载模块是同步的:同步的意味着只有等到请求的模块加载完,当前模块的内容才会运行

    • 这在服务器没什么问题,服务器加载的js文件都是本地文件,加载速度非常快,但是在浏览器中我们后面的一些简单的操作都无法运行

  • 当然,webpack中会把CommonJS转换成浏览器可以执行的代码,所以我们也可以在Vue、React中的模块化开发中使用CommonJS

ESModule
  • ES Module模块采用export和import关键字来实现模块化
    • export负责将模块内的内容导出
    • import负责从其他模块导入内容
  • 采用ES Module将自动采用严格模式:use strict
  • 需要注意的是:如果通过本地加载Html 文件 (比如一个 file:// 路径的文件), 将会遇到 CORS 错误,因 为Javascript 模块安全性需要。
    • 解决方案是在VScode中安装Live Server插件
  • exports关键字
    • 方式一:在语句声明的前面直接加上export关键字

    • 方式二:将所有需要导出的标识符,放到export后面的 {}中

      • 这里的 {}里面不是ES6的对象字面量的增强写法,{}也不是表示一个对象的;
      • 所以: export {name: name},是错误的写法
    • 方式三:导出时取别名

    • 方式四:默认导出,即export default {}的写法

      • 我们可以在每一个模块中定义多个命名导出,但是只允许有一个默认导出。如果有多个默认导出,则后一个覆盖前一个

      • 由命名导出的模块,在导入时必须要用相同的名称

      • 由默认导出的模块,可以用任意的名称导入

方式一、方式二、方式三都是命名导出

// 导出事先定义的特性
export { myFunction,myVariable };

// 导出单个特性(可以导出var,let,
//const,function,class)
export let myVariable = Math.sqrt(2);
export function myFunction() { ... };

export {
  name as fName,
  age as fAge,
  message as fMessage,
  sayHello as fSayHello
}

方式四:默认导出

// 导出事先定义的特性作为默认值
export { myFunction as default };

// 导出单个特性作为默认值
export default function () { ... }
export default class { .. }

// 每个导出都覆盖前一个导出
  • import关键字
    • 方式一:import {标识符列表} from '模块'
      • 这里的{}也不是对象
import { name, age, message, sayHello } from './modules/foo.js';
  • 方式二:导入时给标识符起别名
import { name as wName, age as wAge, message as wMessage, sayHello as wSayHello } from './modules/foo.js';

  • 方式三:将模块功能放到一个模块功能对象(foo
import * as foo from './modules/foo.js';

  • 如果是默认导出的模块,在导入时不需要使用 {},并且可以自己来指定名字

  • import还有动态加载的用法,即import函数

    • 因为浏览器会做预解析,所以import直接写在逻辑代码里没办法运行
    • 因此,如果要在逻辑代码中动态加载模块,要使用import函数

CommonJS与ES Module比较

  • CommonJS的加载过程
    • CommonJS模块加载js文件的过程是运行时加载的,并且是同步的
      • 运行时加载也就是说js引擎在执行js代码的过程中加载模块
      • 同步的就意味着一个文件没有加载结束之前,后面的代码都不会执行
    • CommonJS通过module.exports导出的是一个对象
      • 导出的是一个对象意味着可以将这个对象的引用在其他模块中赋值给其他变量
      • 但是最终他们指向的都是同一个对象,那么一个变量修改了对象的属性,所有的地方都会被修改
  • ES Module加载过程
    • ES Module加载js文件的过程是编译(解析)时加载的,并且是异步的

    • ES Module通过export导出的是变量本身的引用

      • export在导出一个变量时,js引擎会解析这个语法,并且创建模块环境记录(module environment record);
      • 模块环境记录会和变量进行 绑定(binding),并且这个绑定是实时的;
      • 而在导入的地方,我们是可以实时的获取到绑定的最新值的

注意

  • 如果在导出的模块中修改了变化,那么导入的地方可以实时获取最新的变量;
  • 在导入的地方不可以修改变量,因为它只是被绑定到了这个变量上(其实是一个常量)。也就是说,ES Module模式中,模块环境相当于使用一个变量const绑定了导出的引用地址,我们导入的时候不可以更改该地址。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容