CJS的module.exports 、 exports和ESM export default和 export详解

2024-04-14 06:44

本文主要是介绍CJS的module.exports 、 exports和ESM export default和 export详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

webpackg公共源码

function __webpack_require__(moduleId) {if (__webpack_module_cache__[moduleId]) {return __webpack_module_cache__[moduleId].exports;}var module = __webpack_module_cache__[moduleId] = { exports: {} };__webpack_modules__[moduleId](module, module.exports, __webpack_require__);return module.exports;}

结合源码分析以下问题:

  1. commonjs同时有 module.exports 、 exports 的情况 输出的一直都是 module.exports 导出的内容 ,exports 不生效

    分析:这里简化一下代码,可以结合require方法导入的函数,可以看到module.exports赋值后

    module.exports指向了新的变量,这里和第二个参数已经不是同一个对象了,后面exports.xx只是对临时变量进行赋值,并没有什么意义

    解决办法:
    1.统一用exports
    2.用module.exports,需要格外添加module.exports.xxx=value

    var __webpack_modules__ ={"./src/util/math.ts":(module, exports)=>{module.exports ={sum,sub}exports.sumM = sum;exports.subM = sub,}
    }
    
    • 1.esModule(后面简称ESM)模块用commonJS(简称CJS)的reqiure导入后会多包了一层default
    • 2.ESM export default导出从另一个模块导入后不能直接解构赋值,
    // esModule导出,主要代码
    export const formattedDate2 = (date: Date) => {return date;
    };export default {formattedDate,formattedDate2,
    }
    //index.jsimport esModule, { formattedDate2 } from "./util/format";
    // const { formattedDate } = esModule;
    console.log("esModule", esModule, formattedDate2);
    

    同样的简化源码

     var __webpack_modules__ ={"./src/util/format.ts":(__unused_webpack_module, __webpack_exports__, __webpack_require__)=>{__webpack_require__.d(__webpack_exports__, {"default": () => (__WEBPACK_DEFAULT_EXPORT__),formattedDate2,})const __WEBPACK_DEFAULT_EXPORT__ = ({formattedDate: formattedDate,formattedDate2: formattedDate2})}
    }var _util_format__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(./src/util/format.ts");console.log("esModule", _util_format__WEBPACK_IMPORTED_MODULE_0__["default"], _util_format__WEBPACK_IMPORTED_MODULE_0__.formattedDate2)
    

    这里注意直接导入的是获取_util_format__WEBPACK_IMPORTED_MODULE_0__["default"],而解构赋值是直接调用的_util_format__WEBPACK_IMPORTED_MODULE_0__这就是两者 export default 和 export的区别

    //ESM 特有__webpack_require__.d = function (exports, definition) {for (var key in definition) {if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });}}};// hasOwnProperty() 方法返回一个布尔值,表示对象自有属性(而不是继承来的属性)中是否具有指定的属性__webpack_require__.o = function (obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
    

    再看 __webpack_require__.d函数对Module执行了什么操作,通过Object.defineProperty给exports分别声明defaultformattedDate2 属性 的getter方法和声明该属性可枚举

    注意这里没有导出setter方法,所以是不能直接修改导出的变量的,但是我们可以在模块导出setter方法去修改变量(我个人觉得有点像私有变量)。

    // esModule增加如下导出,
    let value = "old";
    const setName = (newValue: string) => {value = newValue;
    };export { value, setName };
    //编译的源码如下
    __webpack_require__.d(__webpack_exports__, {"default": () => (__WEBPACK_DEFAULT_EXPORT__),formattedDate2: () => formattedDate2,setName: () => setName,value: () => value
    }
    

这里回过头看问题就清晰了,问题一require导出ESM模块的默认导出一致(看的webpack教程说以前不一样,可能是webpack5修改的),问题2同上,默认导出的是default属性不能直接解构赋值的

这篇关于CJS的module.exports 、 exports和ESM export default和 export详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/902344

相关文章

Debezium 与 Apache Kafka 的集成方式步骤详解

《Debezium与ApacheKafka的集成方式步骤详解》本文详细介绍了如何将Debezium与ApacheKafka集成,包括集成概述、步骤、注意事项等,通过KafkaConnect,D... 目录一、集成概述二、集成步骤1. 准备 Kafka 环境2. 配置 Kafka Connect3. 安装 D

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

Spring Cloud LoadBalancer 负载均衡详解

《SpringCloudLoadBalancer负载均衡详解》本文介绍了如何在SpringCloud中使用SpringCloudLoadBalancer实现客户端负载均衡,并详细讲解了轮询策略和... 目录1. 在 idea 上运行多个服务2. 问题引入3. 负载均衡4. Spring Cloud Load

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

SQL 中多表查询的常见连接方式详解

《SQL中多表查询的常见连接方式详解》本文介绍SQL中多表查询的常见连接方式,包括内连接(INNERJOIN)、左连接(LEFTJOIN)、右连接(RIGHTJOIN)、全外连接(FULLOUTER... 目录一、连接类型图表(ASCII 形式)二、前置代码(创建示例表)三、连接方式代码示例1. 内连接(I

Go路由注册方法详解

《Go路由注册方法详解》Go语言中,http.NewServeMux()和http.HandleFunc()是两种不同的路由注册方式,前者创建独立的ServeMux实例,适合模块化和分层路由,灵活性高... 目录Go路由注册方法1. 路由注册的方式2. 路由器的独立性3. 灵活性4. 启动服务器的方式5.

Java中八大包装类举例详解(通俗易懂)

《Java中八大包装类举例详解(通俗易懂)》:本文主要介绍Java中的包装类,包括它们的作用、特点、用途以及如何进行装箱和拆箱,包装类还提供了许多实用方法,如转换、获取基本类型值、比较和类型检测,... 目录一、包装类(Wrapper Class)1、简要介绍2、包装类特点3、包装类用途二、装箱和拆箱1、装

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要