• 模块化Common JS 和 ES Module


    目录

    历程

    1.几个函数:全局变量的污染,模块间没有联系

    2.对象:暴露成员,外部可修改

    3.立即执行函数:闭包实现模块私有作用域

    common JS

    module和Module

    过程

    模块依赖:深度优先遍历、父 -> 子 -> 父

    导入:require

    避免重复加载、循环引用:Module缓存

    先加入缓存, 后执行模块内容

    动态加载:任意位置,按需加载

    导出

    对象:exports=module.exports

    非对象:module.exports

    区别

    CommonJS

    运行时加载

    ES Module

    编译时加载

    模块化规范:一个模块=实现特定功能一组方法

    全局污染:共享时,同名变量冲突

    依赖管理:下层 js 能调用上层 js 的方法,但是上层 js 无法调用下层 js 的方法

    历程

    1.几个函数:全局变量的污染模块间没有联系

    1. // 模块A
    2. var ModuleA = {
    3. func1: function() {
    4. // ...
    5. },
    6. func2: function() {
    7. // ...
    8. }
    9. };
    10. // 模块B
    11. var ModuleB = {
    12. func3: function() {
    13. // ...
    14. }
    15. };

    2.对象:暴露成员,外部可修改

    后面提出了对象,通过将函数作为一个对象的方法来实现,但是这种办法会暴露所 有的所有的模块成员,外部代码可以修改内部属性的值

    3.立即执行函数:闭包实现模块私有作用域

    现在最常用的是立即执行函数的写法,通过利用闭包来实现模块私有作用域的建立,同时不会对全局作用域造成污染

    1. //IIFE(立即调用函数表达式)
    2. //创建一个私有作用域,避免变量之间的冲突。然后,通过返回一个对象或函数来暴露模块的公共部分
    3. // 模块A
    4. var ModuleA = (function() {
    5. var privateVar = "private";
    6. function privateFunc() {
    7. // ...
    8. }
    9. return {
    10. publicVar: "public",
    11. publicFunc: function() {
    12. // ...
    13. }
    14. };
    15. })();

    common JS

    module和Module

    module:在 commonjs 中每一个 js 文件都是一个单独的模块

    module 上保存了 exports 等信息之外,还有一个 loaded(bool) 表示该模块是否被加载。

    Module :以 nodejs 为例,整个系统运行之后,会用 Module 缓存每一个module的信息。

    过程

    1. //home.js
    2. const sayName = require('./hello.js')
    3. module.exports = function say(){
    4. return {
    5. name:sayName(),
    6. }
    7. }
    8. //编译进行首尾包装
    9. (function(exports,require,module,__filename,__dirname){
    10. const sayName = require('./hello.js')
    11. module.exports = function say(){
    12. return {
    13. name:sayName(),
    14. }
    15. }
    16. })
    17. //包装函数
    18. function wrapper (script) {
    19. return '(function (exports, require, module, __filename, __dirname) {' +
    20. script +
    21. '\n})'
    22. }
    23. //runInThisContext
    24. eavl(包装后的module)(module.exports, require, module, __filename, __dirname)

    模块依赖:深度优先遍历、父 -> 子 -> 父

    1. //a.js
    2. const getMes = require('./b')
    3. console.log('我是 a 文件')
    4. exports.say = function(){
    5. const message = getMes()
    6. console.log(message)
    7. }
    8. //b.js
    9. const getMes = require('./a')
    10. console.log('我是 b 文件')
    11. exports.say = function(){
    12. const message = getMes()
    13. console.log(message)
    14. }
    15. //main.js
    16. const a = require('./a')
    17. const b = require('./b')
    18. console.log('node 入口文件')

    1. const say = require('./a')
    2. console.log('我是 b 文件')
    3. console.log('打印 a 模块' , say)
    4. setTimeout(()=>{
    5. console.log('异步打印 a 模块' , say)
    6. },0)
    7. exports.say = function(){
    8. const message = getMes()
    9. console.log(message)
    10. }

    导入:require

    避免重复加载、循环引用:Module缓存

    先加入缓存, 后执行模块内容

    加载之后的文件的 module 会被缓存到 Module 上,比如一个模块已经 require 引入了 a 模块,如果另外一个模块再次引用 a ,那么会直接读取缓存值 module ,所以a中的代码只会执行一次

    动态加载:任意位置,按需加载

    require 本质上就是一个函数,那么函数可以在任意上下文中执行,来自由地加载其他模块的属性方法。

    导出

    对象:exports=module.exports

    module.exports 导出的是一个对象时,对象的引用关系是被保留的,这意味着其他模块引入这个对象后,即使该对象后续被修改,其他模块也能看到这些修改。这是因为对象在 JavaScript 中是引用类型,它们的引用关系是保持的。

    1. exports.author = '7'
    2. exports.say = function (){
    3. console.log(666)
    4. }
    5. module.exports ={
    6. author:'7',
    7. say(){
    8. console.log(666)
    9. }
    10. }

    非对象:module.exports

    在循环引用的时候,就容易造成属性丢失的情况发生

    1. module.exports = a // 导出变量
    2. module.exports = [1,2,3] // 导出数组
    3. module.exports = function(){} //导出方法

    区别

    CommonJS

    运行时加载

    在服务器端,同步加载模块的方式是可行的,因为模块通常都在本地。

    ES Module

    编译时加载

    ES模块的结构在编译时就确定下来,模块的依赖关系在代码运行前就已经确定。静态导入导出:方便 tree shaking

    「万字进阶」深入浅出 Commonjs 和 Es Module - 掘金

  • 相关阅读:
    jvm概述
    python之word文档生成
    64、使用 Spring WebFlux 的 WebClient 整合第三方Restful服务
    传统机器学习聚类算法——总集篇
    (黑马出品_02)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
    Express学习(一)
    Nuxt3 初学,基础配置,页面结构搭建,引入element
    java培训技术SpringMVC视图解析器
    java的继承特性和方法重写
    SQL查询本年每月的数据
  • 原文地址:https://blog.csdn.net/qq_28838891/article/details/134489711