npm require 浅拷贝
- 当前 Bug 的表现(可附上截图)
- 预期表现
- 复现路径
- 提供一个最简复现 Demo
小程序会在每个npm包的入口文件前加入一段模块打包代码,类似webpack的,下面是其中 __REQUIRE__ 函数的实现
var __REQUIRE__ = function (modId, source) { if (!__MODS__[modId]) return require(source); if (!__MODS__[modId].status) { var m = { exports: {} }; __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); if ( typeof m.exports === "object" ) { Object.keys(m.exports).forEach( function (k) { __MODS__[modId].m.exports[k] = m.exports[k]; }); if (m.exports.__esModule) Object.defineProperty(__MODS__[modId].m.exports, "__esModule" , { value: true }); } else { __MODS__[modId].m.exports = m.exports; } } return __MODS__[modId].m.exports; }; |
可以看到,这里判断了如果一个模块导出的是一个对象,就会对其做一层的拷贝,这不是浅拷贝,浅拷贝是直接赋值。这一层的拷贝会导致引用出问题
以下是webpack的require实现
function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if (installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false , /******/ exports: {}, /******/ hot: hotCreateModule(moduleId), /******/ parents: (hotCurrentParentsTemp = hotCurrentParents, hotCurrentParents = [], hotCurrentParentsTemp), /******/ children: [] /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId)); /******/ /******/ // Flag the module as loaded /******/ module.l = true ; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } |
可见并没有做一层的拷贝。