当前位置: 首页> 娱乐> 明星 > 电商名字创意名称_个人门户网站_成品网站1688入口网页版_灰色seo推广

电商名字创意名称_个人门户网站_成品网站1688入口网页版_灰色seo推广

时间:2025/7/12 3:12:32来源:https://blog.csdn.net/XiugongHao/article/details/145014924 浏览次数:0次
电商名字创意名称_个人门户网站_成品网站1688入口网页版_灰色seo推广

CommonJS

在 CommonJS 模块中,模块的输出是对象引用的拷贝。这意味着,如果导出的对象在模块内发生了修改,其他地方通过 require 导入的内容也会反映这些更改。

以下是详细说明:

  1. 模块缓存

    • CommonJS 模块在首次被 require 时,模块的代码会执行,导出对象会被创建并存储在缓存中。
    • 后续对该模块的 require 调用将返回缓存中的导出对象。
  2. 引用行为

    • 如果模块导出的是一个对象或数组,外部对该导入对象的修改会影响其他地方导入的对象,因为它们引用的是同一个内存地址。

示例:

moduleA.js:

const data = { count: 1 };function increment() {data.count++;
}module.exports = { data, increment };

main.js:

const moduleA = require('./moduleA');
console.log(moduleA.data.count); // 输出: 1moduleA.increment();
console.log(moduleA.data.count); // 输出: 2const anotherImport = require('./moduleA');
console.log(anotherImport.data.count); // 输出: 2

解释

  • module.exports 是一个对象的引用。
  • require('./moduleA') 返回缓存中相同的引用。
  • 修改 moduleA.data 会反映在所有导入中。

注意:

  • 如果直接导出原始值(如数字、字符串等),这将是一个值的拷贝,因为原始值是不可变的。例如:

moduleB.js:

let count = 1;function increment() {count++;
}module.exports = { count, increment };

main.js:

const moduleB = require('./moduleB');
console.log(moduleB.count); // 输出: 1moduleB.increment();
console.log(moduleB.count); // 输出: 1(值的拷贝,不会自动更新)

总结

  • CommonJS 模块导出的对象是引用的拷贝。
  • 如果导出的是原始值,则导入后是值的拷贝,不会随着模块内的变化自动更新。

ES Module

在 ES Modules(ESM)中,模块的导出是通过引用的方式共享的。这意味着:

  1. 导出的值是动态绑定的

    • 导入的内容会实时反映模块中导出的最新状态(如果导出的值是对象或可变变量)。
    • ES Modules 会确保模块导出和导入的值保持同步。
  2. 与 CommonJS 的区别

    • CommonJS 在模块加载时会将导出的内容生成一次并缓存(静态快照,原始值不会同步更新)。
    • ESM 的导出是动态绑定的,即使导出的是原始值,更新模块内的值后,导入的地方也会反映出变化。

1. 对象引用
如果导出的是对象,导入的地方和模块内部共享同一个引用。

moduleA.mjs:

export const data = { count: 1 };export function increment() {data.count++;
}

main.mjs:

import { data, increment } from './moduleA.mjs';console.log(data.count); // 输出: 1increment();
console.log(data.count); // 输出: 2

解释

  • data 是通过引用共享的,模块内部修改会直接反映到导入的地方。

2. 原始值(动态绑定)
如果导出的是原始值(如数字、字符串),模块内部更新的值会同步到导入的地方。

moduleB.mjs:

export let count = 1;export function increment() {count++;
}

main.mjs:

import { count, increment } from './moduleB.mjs';console.log(count); // 输出: 1increment();
console.log(count); // 输出: 2

解释

  • count 是动态绑定的,尽管它是原始值,模块内部的更新会反映到导入的地方。

ESM 的特点:

  1. 静态结构

    • ES Modules 是在编译时解析的,importexport 必须位于顶层。
    • 无法在运行时动态导入或导出(但可以使用 import() 动态加载模块)。
  2. 实时绑定

    • ESM 的导出是动态绑定的,导入的值会随模块内的更新而更新。
  3. 单例模式

    • ES Modules 是单例的,多次导入同一个模块时,得到的都是同一个模块实例。

对比总结

特性CommonJSES Modules
导出机制值的拷贝(原始值),引用拷贝(对象)动态绑定
导入时机运行时(动态加载)编译时(静态加载)
更新机制静态快照实时更新
模块缓存
用法require()import/export

因此,ESM 更适合处理动态绑定和模块间实时同步的场景。

其他区别

1. 模块加载时机

  • CommonJS:模块加载是 同步 的,模块加载时会立即执行,并返回模块的导出内容。因此,require 语句会阻塞,直到模块完全加载并执行完成。
  • ESM:模块加载是 异步 的,在浏览器和 Node.js 中,ESM 模块在加载时不会阻塞,尤其是在浏览器环境下,模块加载会是异步的。

2. 文件扩展名

  • CommonJS:支持 .js, .json, 和 .node 扩展名的文件。模块导入时,如果没有扩展名,Node.js 会自动尝试加载 .js.json.node 文件。
  • ESM:在 Node.js 环境下,ESM 强制要求指定扩展名,除非使用 .js 文件且该文件是 ES Module(在 package.json 中指定 "type": "module")。这意味着必须明确指定扩展名,如 import x from './module.mjs'import x from './module.js'

3. 模块的加载方式

  • CommonJS:在执行 require 时,模块被加载并执行一次,之后会缓存模块的导出内容。模块执行的顺序是按调用 require 的顺序同步执行。
  • ESM:ESM 模块的加载是 按需 加载的,ESM 模块会被动态解析并可能会被异步加载。ESM 模块会被延迟执行,且加载过程支持静态分析,允许更强大的工具进行优化和死代码删除。

4. importexport 语法

  • CommonJS

    • 导入:const foo = require('foo');
    • 导出:module.exports = foo;exports.foo = foo;
  • ESM

    • 导入:import foo from 'foo';import { bar } from 'foo';
    • 导出:export default foo;export { foo };

    ES Modules 使用静态的 importexport 语法,在编译时就可以解析出模块的依赖关系,而 CommonJS 使用动态的 requiremodule.exports,只能在运行时解析。

5. this 的行为

  • CommonJS:在模块中,this 默认指向 module.exports。这意味着如果你没有显式地导出模块,this 将指向一个空对象({})。

    // CommonJS
    console.log(this); // 输出: {}
    this.foo = 'bar';
    console.log(module.exports); // 输出: { foo: 'bar' }
    
  • ESMthis 在 ESM 模块中并不会指向 exportsmodule.exports,它指向 undefined。在 ESM 中,exportimport 被静态解析,this 并不是用于模块导出的机制。

    // ESM
    console.log(this); // 输出: undefined
    

6. 异步性

  • CommonJS:模块加载是同步的,因此适合于服务器端的环境,尤其是在 Node.js 中,文件读取通常是同步的。

  • ESM:ESM 支持异步加载模块,尤其是在浏览器中,ESM 是按需加载的,可以延迟模块的加载,提高性能。对于 Node.js,也提供了 import() 异步加载的能力。

    // 使用动态导入
    import('./module.js').then(module => {console.log(module);
    });
    

7. 循环依赖处理

  • CommonJS:处理循环依赖时,CommonJS 会在模块第一次加载时返回模块的当前状态,后续 require 调用会返回这个已经部分执行的模块。这意味着如果一个模块还未完全执行,其他模块就可以访问到它的部分导出。

  • ESM:ESM 通过引入 动态绑定 的方式来处理循环依赖。如果模块 A 导入模块 B,而模块 B 又导入模块 A,模块 A 和 B 中的导出会是动态的绑定关系,始终反映最新的值。

8. 命名空间导出

  • CommonJS:导出的内容是一个对象,可以直接添加到 module.exportsexports 上,这通常意味着你可以在导出时使用任意结构(如对象、数组、函数等)。

    // CommonJS 导出
    module.exports = { foo: 'bar', baz: 'qux' };
    
  • ESM:ESM 使用静态导出和导入的机制,且导入时会自动生成一个“命名空间”对象。这意味着你可以选择性地导入模块的部分功能。

    // ESM 导出
    export const foo = 'bar';
    export const baz = 'qux';
    

9. requireimport 的行为

  • CommonJSrequire 是一个动态函数,可以在任何地方使用,因此可以在条件语句、循环中动态加载模块。

    if (condition) {const module = require('./module');
    }
    
  • ESMimport 是静态的,必须在模块的顶部使用,并且不能在条件语句、循环中动态加载。import 的静态特性使得打包工具(如 Webpack)能够优化模块的加载顺序和去除死代码。

    // ESM 只能在顶部使用
    import { foo } from './module';
    

10. 浏览器支持

  • CommonJS:原生不支持浏览器,通常需要通过打包工具(如 Webpack、Browserify)进行转换。

  • ESM:ESM 从一开始就设计为浏览器支持的标准。现代浏览器原生支持 <script type="module"> 标签,可以直接加载 ESM 模块。Node.js 在 v12+ 也原生支持 ESM。

11. 模块作用域

  • CommonJS:模块是封装在一个函数中,模块内部的变量和函数默认不污染全局作用域。

  • ESM:ESM 的模块作用域也类似,每个模块都有自己的作用域,且不污染全局作用域。ESM 具有更强的静态分析能力和模块系统支持。


总结

特性CommonJSES Modules
加载方式同步加载异步加载
语法require(), module.exportsimport, export
模块缓存模块首次加载时缓存模块首次加载时缓存
模块作用域模块内有自己的作用域,this 默认指向 module.exports模块内有自己的作用域,this 指向 undefined
循环依赖部分执行的模块对象动态绑定,解决循环依赖
扩展名支持 .js, .json, .node强制需要扩展名(如 .js, .mjs
适用场景主要用于服务器端,Node.js适用于浏览器和 Node.js,支持异步加载
关键字:电商名字创意名称_个人门户网站_成品网站1688入口网页版_灰色seo推广

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: