每天3分钟,重学ES6-ES12(十八) CJS

2022-09-19 14:14:25 浏览数 (1)


theme: juejin

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情

每天3分钟,重学ES6-ES12文章汇总

前言

今天开始和大家一起系统的学习ES6 ,每天3分钟,用一把斗地主的时间,重学ES6 ,前面我们介绍了模块化的历史,今天介绍模块化处理方案

CommonJS

CommonJS规范和Node关系

  • common Js 是一个规范,指出是在浏览器以外的地方,可以简称为CJS
  • Node 是commonJs 在服务器端一个具体有代表性的一个实现
  • webpack打包工具具备对commonJS的支持和转换
  • node 中每一个js文件都有是一个单独的模块
  • 包括CommonJS规范的核心变量:exports,module.exports, requrie

导出方式

exports.a

module.exports ={a:a}

代码语言:javascript复制
// 源码
module.exports = {} 
exports = module.exports 
//最终能导出的一定是module.exports()

内部原理

代码语言:javascript复制
// main.js
const why = require("./why.js")

console.log(why)

setTimeout(() => {
  console.log(why.name)
  why.name = "james"
}, 1000)

// why.js
const info = {
  name: "why",
  age: 18,
  foo: function() {
    console.log("foo函数~")
  }
}

setTimeout(() => {
  // info.name = "kobe"
  console.log(info.name)
}, 2000)

module.exports = info

两个文件 执行node main.js 输出结果为

{ name: 'why', age: 18, foo: [Function: foo] } why james

先打印why对象,然后打印why 修改why name 打印 james

由此可见,require 引入的文件是加载时执行

require执行细节

require是一个函数,可以帮助我们引入一个文件(模块)中导出的对象。

require(X)

查找规则

  • 1.如果X是node的一个核心模块,如http path 则直接返回核心模块,并停止查找
  • 2.如果X是一个路径
    • 2.1.将X当作是文件名在对应的目录下查找
      • 如果有后缀名,按照后缀名的格式查找对应的文件
      • 如果没有后缀名,会按照顺序
        • 直接查找文件X > 查找X.js文件 > 查找X.json文件>查找X.node文件
    • 2.2.如果没有找到对应的文件,将X作为一个目录
      • 查找目录下的index文件
        • 查找X/index.js文件>查找X/index.json文件>查找X/index.node文件
  • 3.非路径也非核心模块(第三方包)
    • 每层级依次去寻找node_modules 如果都没找到,那么报错:not found

模块的加载过程

  • 结论一:模块在被第一次引入时,模块中的js代码会被运行一次
  • 结论二:模块被多次引入时,会缓存,最终只加载(运行)一次
    • 这是因为每个模块对象module都有一个属性:loaded。
    • 为false表示还没有加载,为true表示已经加载;
  • 结论三:如果有循环引入,Node采用的是深度优先算法,寻找模块

CommonJS规范缺点

  • CommonJS加载模块是同步的:
    • 同步的意味着只有等到对应的模块加载完毕,当前模块中的内容才能被运行;
    • 这个在服务器不会有什么问题,因为服务器加载的js文件都是本地文件,加载速度非常快;
  • 如果将它应用于浏览器呢?
    • 浏览器加载js文件需要先从服务器将文件下载下来,之后再加载运行;
    • 那么采用同步的就意味着后续的js代码都无法正常运行,即使是一些简单的DOM操作;
  • 所以在浏览器中,我们通常不使用CommonJS规范:
    • 当然在webpack中使用CommonJS是另外一回事;
    • 因为它会将我们的代码转成浏览器可以直接执行的代码;
  • 在早期为了可以在浏览器中使用模块化,通常会采用AMD或CMD:
    • 但是目前一方面现代的浏览器已经支持ES Modules,另一方面借助于webpack等工具可以实现对CommonJS或者ESModule代码的转换;
    • AMD和CMD已经使用非常少了,所以这里我们也不展开介绍了。

0 人点赞