You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
importfoofrom"module";foo(1,2);// <- called without this (undefined/global object)
打包处理后会被转化成如下的样子:
var__WEBPACK_IMPORTED_MODULE_1__module__=__webpack_require__(1);Object(__WEBPACK_IMPORTED_MODULE_1__module__.foo)(1,2);// ^ called without this (undefined/global object)
var__WEBPACK_IMPORTED_MODULE_1__module__=__webpack_require__(1);__WEBPACK_IMPORTED_MODULE_1__module__.foo(1,2);// ^ called this = __WEBPACK_IMPORTED_MODULE_1__module__
import{foo}from"module";//_____^foo(1,2);// <- called without this (undefined/global object)
或者第二个代码块应该是
var__WEBPACK_IMPORTED_MODULE_1__module__=__webpack_require__(1);Object(__WEBPACK_IMPORTED_MODULE_1__module__.default)(1,2);//___________________________________________^// ^ called without this (undefined/global object)
import{foo}from"module";foo(1,2);// <- called without this (undefined/global object)
事实上,上面这段代码 webpack 转换后是这样
var__WEBPACK_IMPORTED_MODULE_1__module__=__webpack_require__(1);Object(__WEBPACK_IMPORTED_MODULE_1__module__.b/* foo */)(1,2);// ^ called without this (undefined/global object)
webpack中的对象构造器
昨天在webpack这个Issue上面有人提到了个很有趣的问题,大概是说了3版本的webpack生成的代码是如何做到的引入了新的模块。比如像下面这样:
打包处理后会被转化成如下的样子:
这背后的原因是webpack必须把保留潜在的语义上的this给函数foo。如果你是像下面这样生成代码的话
在foo里面用到this的地方会被绑定到__WEBPACK_IMPORTED_MODULE_1__module__上,这样一来就和我们上面的ESM语义是不相符的了。很显然还有很多其他不同的方法来实现这一效果,Tobias Koppers研究了这其中的很多细节,尝试了多种方法,最终决定使用Object constructor来做
不幸的是 事实上对象构造函数在某些情况下仍然带来了一些不必要的损失,因为直到现在TurboFan(V8底层)还没有搞清楚怎么一回事,我简单的写了个benchmark
在V8.5.5(使用Crankshaft的最新版本)和V8.6.1(当前使用TurboFan的beta版本)中,从结果看来webpack的选择是正确的做法??
使用identity函数的版本达到了最好的效果(最接近直接调用的结果,目前webpack无法实现)。其次就是使用Function.proptype.call的方式了,然后使用Object constructor的方式就是最慢的了,是直接执行的2.3倍耗时
导致这一事件的原因是TurboFan和Crankshaft在执行callViaIdentity的时候将identity函数进行了内联(不知道C++ inline的自己去面壁),因此几乎完全没有造成什么额外的消耗
但是调用Object constructor的时候没有被内联(我也看不懂汇编,不过明显看到多出来的步骤吧)
在这种情况下,在o.foo的环境中调用Object constructor相当于是一个noop函数(不知道的去面壁),就跟调用identify函数一样。我们可以在规范中找到相应的描述
ToObject抽象操作是js中对象的定义操作(closures就是普通的js对象)。所以我们就是得教会处理TurboFan这样的调用
当能够证明这个value是个object的时候。这就足以满足webpack的情况了,因为这里传递给Object constructor的是从module中拿到的对象,他们是始终被V8引擎所跟踪的,所以TurboFan能够追溯到module.hot的来源就是某个常量对象。所以能够添加一些Object constructor相关的黑魔法到TurboFan上面来解决这个issue
可以看到上面性能上有了的提升,或多或少的改变了些代码
并且webpack3生成的打包资源,也不回因为这些问题而有那么大差异了
嘛,其实全文读下来你会发现没说什么东西,而且现在的新版本上这几种操作的速度基本一致了。不过这也让我们知道了不断深挖的重要性
The text was updated successfully, but these errors were encountered: