如何实现通过npm启动应用后可在Chrome控制台调用的函数?
为什么
SoundModule能在Chrome控制台直接调用? 前阵子我碰到一段类似的代码,本身逻辑没什么特别,但有个点很有意思:启动应用后居然能直接在Chrome控制台里调用SoundModule.playMusic();。结合你给出的npm脚本配置和代码片段,我来拆解下背后的原因:
首先看你的local脚本配置:
"local": "node node_modules/rollup/bin/rollup src/client/main.js --o client/bundle.js --f es && node --max-old-space-size=8192 index"
这里Rollup用--f es参数把代码打包成了ES模块格式,但这并不代表所有变量都会被隔离在模块作用域里。关键在于**SoundModule最终被暴露到了浏览器的全局window对象上**,所以控制台(它本身就运行在全局作用域)能直接访问到它。
具体来说,可能是这几个原因:
- 代码本身的全局暴露:你的核心代码里
SoundModule是个普通对象,如果在代码里直接把它挂载到了window上(比如加了window.SoundModule = SoundModule;这行),那不管怎么打包,它都会成为全局属性,控制台自然能调用。 - Rollup打包的作用域泄漏:虽然用了ES模块格式,但如果你的
src/client/main.js里没有用export导出SoundModule,反而让它留在了顶级作用域,而Rollup的配置又没有严格隔离模块作用域(比如某些情况下打包后的代码没有用IIFE包裹),那这个变量就会泄漏到全局window中。 - 脚本加载方式问题:如果打包后的
bundle.js是通过普通的<script>标签加载(没有加type="module"),那ES模块的顶级作用域会被当成全局作用域,里面的变量直接变成window的属性,控制台就能直接访问。
举个简单的例子,要是你的代码里有这么一行:
// 在定义SoundModule后添加 window.SoundModule = SoundModule;
那百分百能在控制台直接调用SoundModule.playMusic()。
本质上就是SoundModule没有被限制在模块私有作用域里,而是跑到了全局window对象上,所以控制台能直接拿到它。
内容的提问来源于stack exchange,提问作者Igor Santos de Lima




