You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在导入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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 22:57:03