Loading

Js-CommonJs模块化&ES6模块化

  • 将程序文件依据一定的规则拆分成多个文件,这种编码方式就是模块化的编码方式
  • 拆分出来的每个文件就是一个模块,模块中的数据都是私有的,模块之间互相隔离
  • 主流的模块化规范:ES6模块化、CommonJs模块化
  • 模块化的核心思想就是:模块直接是隔离的,通过导入和导出的方式进行数据和功能的共享
    • 导出:使模块公开其内部的一部分,使这些内容可以被其他模块使用
    • 导入:模块引用和使用其他模块导出的内容

CommonJs模块化-在node js环境下

CommonJS 主要是为服务端设计的。在 Node.js 中,每个.js 文件被视为一个 CommonJS 模块。

Node.js 有自己的模块加载系统,它会自动识别require语句并加载对应的模块。当你在 Node.js 中使用require时,它会按照一定的规则在本地文件系统中查找模块文件

CommonJs主要用于服务端的Js运行环境(node的默认模块化规范,新版的node已经支持es6的模块化,但它默认任然使用的是CommonJs)

导出(暴露)

每个模块内部的this、exports、modules.exports在初始化时,都指向一个空对象,该对象就是当前模块导出的数据

  1. 使用exports导出

    const info = "info"
    
    const test = "test"
    
    function getInfo() {
        return info
    }
    
    // 导出(暴露当前模块的指定属性方法)  导出自定义属性、方法,值是指定的值、方法
    // exports默认是一个空对象
    exports.info = info
    exports.t = test
    exports.getInfo = getInfo
    
    
    
    
  2. 使用module.exports导出

    module.exports.info = info // 等同于exports.info = info
    
    // 可以直接赋值一个对象
    module.exports = {
      info,
      test,
      getInfo
    }
    
  3. 使用this (node js)

    this.info = info
    

无论如何修改导出对象,最终导出的都是module.exports的值

exports是对module.exports的初始引用,仅为了方便给导出对象添加属性,所以不能使用exprots = {}的方式导出数据

引入

require是用于导入其他模块的函数。在 Node.js 环境下,一个文件就是一个 CommonJS 模块,通过require可以将其他模块的功能引入到当前模块中使用

// require跟要引入的路径,data是一个对象,包含引入的数据、方法
const data = require('./a.js')

// 调用
data.info()
// 直接解构
const {info,test} = require('./a.js')
// 调用
info()
数据隔离原理

在 CommonJS 中,每个文件被视为一个独立的模块,模块拥有自己独立的作用域。这就好比每个模块都被装在一个独立的盒子里,盒子里的变量、函数等元素不会自动暴露在盒子外面,也不会和其他盒子里的内容相互干扰

可以理解每个文件被自动封装到一个函数里面,每个模块有自己的作用域,然后有module等参数,将要暴露的对应数据传入到module中,在其他模块使用module中的数据

CommonJS 采用同步加载模块的方式。当一个模块(比如moduleA)通过require加载另一个模块(比如moduleB)时,会暂停moduleA的执行,先去加载并执行moduleB。在这个过程中,moduleB的变量和函数定义都在自己的作用域内进行,不会影响moduleA已经定义的变量和函数

CommonJS 有模块缓存机制。当一个模块第一次被加载后,其导出的对象(通过module.exports)会被缓存起来。再次加载同一个模块时,直接从缓存中获取,而不是重新执行模块的代码。这种缓存机制不仅提高了性能,还进一步加强了模块间的数据隔离

浏览器端运行

CommonJs简称为CJS,最初是给服务端使用的,NodeJs默认支持CJS,但是浏览器端默认不支持,可以借助browserify编译,支持浏览器端运行

  1. 安装browserify

     npm i browserify  -g
    
  2. 编译文件

    # a.js是要编译的目标文件,-o生成到当前目录, build_a.js 是编译后要生成的文件名
    browserify a.js -o build_a.js     
    

ES6模块化

es6模块化规范是一个官方标准,在语言标准的层面上实现了模块化功能,浏览器、服务端均支持该规范

基本使用
  1. 暴露

    const info = "info"
    
    
    // 在想暴露出去的数据、方法前 写export关键字
    export const test = "test"
    
    export function getInfo() {
        return info
    }
    
    
  2. 引入

    //  import 表示导入
    //  * 代表所有,  as data 表示全部数据赋值给一个名字data的对象
    // from 后跟对应模块路径
    import * as data from './a.js'
    
    // 调用
    data.test
    
  3. 在标签中

    <!-- type="module" 属性,表明引入的 b.js 文件是作为一个 ES 模块 -->
    <!-- 当type="module"时,JavaScript 代码以模块的形式存在,每个模块都有自己独立的作用域。这就好比每个模块是一个独立的房间,房间里的变量和函数不会自动暴露到外面的 “全局空间” 中 -->
    <script type="module" src="./b.js"></script>
    
在node中运行ES6模块

第一种方式:

模块文件后缀修改为.mjs,引入什么都是.mjs

第二种方式:

在package.json文件中配置 {"type":"module"}

导出数据
分别导出

每个需要导出的数据前 + exports ,就是分别导出

统一导出
// export后面是包含当前模块所有需要导出的内容
export {info,test,getInfo}
默认导出

一个文件中只能有一个默认导出

// default默认导出,后面直接跟value   相当于{default:1000}
export default 1000


// {default:"aaaa"},info是当前文件变量,值是aaaa
export default info


// 默认导出一个对象,{default:{name:'aaaa',count:1000}}
export default {
    name: info,
    count: 1000
}
多种导出方式混用
// 分别导出
export function getInfo() {
    return info
}


// 统一导出
export {info}



// 默认导出
export default test
导入数据
  1. 导入全部-适用于全部导出方式

    // * 代表所有
    import * as data from './a.js'
    
  2. 命名导入-适用于分别导出、统一导出

    // 接收的key和需要暴露的key一致,分别接收对应的数据
    import {info,test} as data from './a.js'
    
    // 如果不想使用原先的key,可以使用as关键字  起一个别名
    import {info as infos ,test} as data from './a.js'
    
  3. 默认导入-适用于默认导出

    // 使用任意一个变量接收默认导出的数据
    import aaaaa as data from './a.js'
    
  4. 混合导入

    // 先接收default,
    import aaa,{info,test} from './a.js'
    
  5. import可以不接收任何数据

    // a.js中有调用的都会执行
    import './a.js'
    
posted @ 2024-12-06 11:42  木子七  阅读(145)  评论(0)    收藏  举报