一、源代码
// 1.定义了一个对象, 对象里面放的是我们的模块映射
var __webpack_modules__ = {
"./src/es_index.js":
(function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
// 调用r的目的是记录时一个__esModule -> true
__webpack_require__.r(__webpack_exports__);
// _js_math__WEBPACK_IMPORTED_MODULE_0__ == exports
var _js_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/js/math.js");
console.log(_js_math__WEBPACK_IMPORTED_MODULE_0__.mul(20, 30));
console.log(_js_math__WEBPACK_IMPORTED_MODULE_0__.sum(20, 30));
}),
"./src/js/math.js":
(function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
__webpack_require__.r(__webpack_exports__);
// 调用了d函数: 给exports设置了一个代理definition
// exports对象中本身是没有对应的函数
__webpack_require__.d(__webpack_exports__, {
"sum": function () { return sum; },
"mul": function () { return mul; }
});
const sum = (num1, num2) => {
return num1 + num2;
}
const mul = (num1, num2) => {
return num1 * num2;
}
})
};
// 2.模块的缓存
var __webpack_module_cache__ = {};
// 3.require函数的实现(加载模块)
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;
}
!function () {
// __webpack_require__这个函数对象添加了一个属性: d -> 值function
__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] });
}
}
};
}();
!function () {
// __webpack_require__这个函数对象添加了一个属性: o -> 值function
__webpack_require__.o = function (obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
}();
!function () {
// __webpack_require__这个函数对象添加了一个属性: r -> 值function
__webpack_require__.r = function (exports) {
if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
}
Object.defineProperty(exports, '__esModule', { value: true });
};
}();
__webpack_require__("./src/es_index.js");
二、解析
- 调用r函数的目的是给exports对象增加一些属性记录一个_esModule
- 如果支持Symbol,还会加一个属性'Module'
- 相当于做一个标记,判断加载的模块是不是esModule
__webpack_require__.r = function (exports) {
if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
}
Object.defineProperty(exports, '__esModule', { value: true });
};
- 注意的是require函数的实现和CommonJS里require函数的实现基本是一样的
- esModule不一样的是require这个函数本身对象上添加了d,o,r函数(函数本身也是一个对象)
- o函数目的:检测这个属性属不属于这个对象
第一个代码块最后一行执行函数
根据key取到的函数去执行(在CommonJS加载中有写,可以看一下上一篇)
1. 首先会调用r函数,目的就是为了做一个记录,记录它是一个ESModule{value: true}
2. 注: 执行 __webpack_modules__对象的函数是在require函数的实现(3.)
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
3. 在这里注意传入参数的对比(因为有点多,就容易看乱)
function (__unused_webpack_module, __webpack_exports__, __webpack_require__);
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
(函数参数对比)
module.exports的exports 是 var module里的exports: {}
(变量解释)
__webpack_require__.r(__webpack_exports__);这样把参数传到Object.defineProperty(exports)
这样也就意味这exports的属性为true
4.调用__webpack_require__函数加载math模块
math模块有是一个函数,并且调用r函数,验证是esModule模块
5.这里有点不同的地方是调用d函数
d函数定义了两个参数 通过for循环遍历definition
webpack_require.d = function (exports, definition) {}
这里需要注意一个函数
__webpack_require__.d(__webpack_exports__, {
"sum": function () { return sum; },
"mul": function () { return mul; }
});
第二个参数definition,就是这里传入的对象
6.在d函数中遍历了这个对象,并且调用o函数,验证这个key属不属于这个对象(判断definition里是否
有key的属性,并且判断exports里没有key的属性)
(这一块我觉得应该是这样的,我参考的资料里说的是判断让definition和exports都有这个key)
(这样做的话,那么还要调用下面defineProperty函数往里面定义key就没有意义)
7.调用Object.defineProperty开始往exports里面定义这个key(来自于注意的那个函数的key),这里
重写了get方法。通过类似与exports["sum"]取值的时候,本质上会去调get方法,就会从definiton
里面根据key取出函数。 函数里面又把函数返回了。(还是需要注意的那个函数)
这里其实相当于给exports做了一个代理,definition是它的代理。
注意:exports对象本身里面是没有对应的函数的。通过取值的时候,调get去返回要执行的函数。
最后函数返回函数,调用的就是const定义的那两个函数(代码中很容易找见)。
8.最终__webpack__require__函数返回exports对象
即 _js_math__WEBPACK_IMPORTED_MODULE_0__ == exports
console.log((0, func)(20, 30))这样写和直接执行一个函数没有区别
console.log(func(20, 30))
所以本质上就是从exports里取mul,sum
通过代理,找到相对应的函数,并打印出结果。
参考:coderwhy老师
注:如果哪里有问题,可以指正 欢迎讨论!