如何在导入jQuery后重新初始化以切换window和document引用?
问题
jQuery会在import时完成初始化。若window和window.document存在(且不存在module),jQuery会保存这些引用并持续使用。
是否有办法在importjQuery后对其进行“重新初始化”或“重置”,使其指向不同的window和document引用?
解决方案
核心原理
jQuery在ES/CommonJS模块环境下的初始化逻辑是:
- 导入时如果全局存在
window.document,直接绑定到该window生成实例 - 若不存在,则返回一个工厂函数,允许传入自定义
window创建新实例
但模块缓存机制会让首次导入的jQuery实例被复用,要实现全局重置,必须同时处理模块缓存清除和实例引用替换。
1. 清除jQuery模块缓存
Node.js会缓存已导入的模块,所以要让jQuery重新执行初始化逻辑,必须先清除其缓存:
function clearJQueryCache() { // 清除CommonJS模块缓存 if (typeof require !== 'undefined' && require.cache) { const jqueryPath = require.resolve('jquery'); delete require.cache[jqueryPath]; } }
2. 全局重置jQuery实例
清除缓存后,重新导入jQuery会返回工厂函数,传入目标window生成新实例,并替换全局和已导入的引用:
async function resetJQueryForWindow(window) { clearJQueryCache(); // 重新导入得到工厂函数 const jQueryFactory = (await import('jquery')).default; const newJQuery = jQueryFactory(window); // 更新全局变量,适配全局使用的场景 globalThis.jQuery = newJQuery; globalThis.$ = newJQuery; // 更新CommonJS模块导出,适配静态导入的场景 if (typeof require !== 'undefined') { const jqueryModule = require('jquery'); Object.assign(jqueryModule, newJQuery); jqueryModule.default = newJQuery; } return newJQuery; }
3. 适配你的测试用例
修复测试用例1
修改parseHtml函数,每次导入前清除缓存,确保使用当前window生成新实例:
async function parseHtml(fileName) { const dom = await JSDOM.fromFile(fileName, { url: 'http://localhost', runScripts: 'dangerously', resources: 'usable', pretendToBeVisual: true, }); const window = dom.window; clearJQueryCache(); const jQueryFactory = (await import('jquery')).default; const $ = jQueryFactory(window); return { document: window.document, jquery: $(`html`), }; }
修复测试用例2
修改test-setup.js,调用重置函数确保全局jQuery绑定到目标window:
import { JSDOM} from 'jsdom' function clearJQueryCache() { if (typeof require !== 'undefined' && require.cache) { const jqueryPath = require.resolve('jquery'); delete require.cache[jqueryPath]; } } async function resetJQueryForWindow(window) { clearJQueryCache(); const jQueryFactory = (await import('jquery')).default; const newJQuery = jQueryFactory(window); globalThis.jQuery = newJQuery; globalThis.$ = newJQuery; if (typeof require !== 'undefined') { const jqueryModule = require('jquery'); Object.assign(jqueryModule, newJQuery); jqueryModule.default = newJQuery; } return newJQuery; } export async function parseHtmlWithDynamicImport(fileName) { const dom = await JSDOM.fromFile(fileName, { url: 'http://localhost', runScripts: 'dangerously', resources: 'usable', pretendToBeVisual: true, }); const $ = await resetJQueryForWindow(dom.window); return { document: dom.window.document, jquery: $(`html`), }; }
注意事项
- 模块缓存清除仅在Node.js环境有效,浏览器中ES模块缓存无法主动清除,需通过测试框架隔离每个测试用例
- 若生产代码依赖全局
$/jQuery,必须确保全局变量被正确替换 - 第三方库依赖的jQuery实例,可能需要同步更新或使用
jQuery.noConflict()释放旧实例
内容的提问来源于stack exchange,提问作者Daniel Kaplan
相关产品推荐
相关产品推荐

