下面是一些人为的代码:
// index.js
import { log } from './log';
log('hello world');
// log.js
export const log = string => console.log(string);
在没有配置的情况下构建它会产生以下字符串化源:
"__webpack_require__.r(__webpack_exports__);n/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./log */ "./src/log.js");nnnObject(_log__WEBPACK_IMPORTED_MODULE_0__["log"])('hello world');nn//# sourceURL=webpack:///./src/index.js?")
我感兴趣的一点是:
"Object(_log__WEBPACK_IMPORTED_MODULE_0__["log"])('hello world');"
我一辈子都无法弄清楚为什么日志函数被传递到Object
调用中。 我已经查看了引入它的提交,但是尝试将带有上下文的函数传递到该调用中似乎并没有解除绑定它们——它只会按原样返回引用。
任何帮助弄清楚为什么存在这一点
将不胜感激。将导出包装在对 Object 构造函数的调用中的原因是将导出作为纯函数调用,而不是 Webpack 导出对象上的方法。
Webpack 在 ES6 模块方面没有严格执行规范,而是通过将导出转换为 Webpack 导出对象的属性来简化事情,而不是静态绑定。当一个函数被添加到 JavaScript 中的对象时,它就变成了一个"方法",当该函数作为方法调用时,this
引用它定义的对象。
在您的示例中,Webpack 避免将模块导出作为导出对象上的方法调用。
_log__WEBPACK_IMPORTED_MODULE_0__["log"]('hello world') // WRONG invoking `log` as a method
与
Object(_log__WEBPACK_IMPORTED_MODULE_0__["log"])('hello world') // RIGHT invoking `log` as a function
他们以一种巧妙的方式使用 Object 构造函数,因为它只会返回未经修改地传递给它的任何函数。他们可以通过使用额外的变量赋值来完成同样的事情。
const temp = _log__WEBPACK_IMPORTED_MODULE_0__["log"]
temp('hello world')
请参阅此处的 Webpack 测试以处理 ES6 模块的this
绑定,以及有关导出箭头函数的违反 ES6 模块规范的问题。
另请参阅有关应在 ES6 模块范围内undefined
this
的文档,因为模块始终处于严格模式,其中函数体中的this
undefined
而不是window
或对导出对象的引用。