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

迁移Firefox30前Greasemonkey脚本至GM4+:如何替换unsafeWindow并获取页面jQuery?

Greasemonkey 4+ 迁移:获取页面jQuery & 替换unsafeWindow指南

嘿,我帮你梳理下GM4+迁移时遇到的这个问题——毕竟GM从旧版本到4+的沙盒变化确实坑了不少人!

为什么旧方法失效了?

GM4+采用了严格的内容脚本沙盒,脚本运行的window和页面本身的window完全是两个独立环境。旧代码里的unsafeWindow.jQuery能直接拿页面jQuery,是因为unsafeWindow直接指向页面的全局对象,但GM4+默认禁用了这个权限;而你试的window.jQuery,拿的是脚本沙盒里的window,自然找不到页面的jQuery,所以会报ReferenceError。

解决方案1:用unsafeWindow(简单直接,需权限)

如果你能接受少量安全风险(毕竟unsafeWindow会让脚本直接接触页面环境),这是最快的方法:

  1. 在脚本开头的元数据里添加权限声明:
    // @grant unsafeWindow
    
    (如果之前没加@grant,GM会启用"无权限模式",此时unsafeWindow不可用)
  2. 然后就可以像旧版本一样获取jQuery:
    var $ = unsafeWindow.jQuery;
    // 测试下是否可用
    console.log('页面jQuery版本:', $.fn.jquery);
    

解决方案2:安全注入获取(推荐,无高权限依赖)

如果不想用unsafeWindow(避免页面脚本篡改全局对象带来的风险),可以通过向页面注入脚本,让页面主动把jQuery传递给GM脚本:

// 步骤1:向页面注入一个小脚本,获取jQuery并通过postMessage发送
const injectScript = document.createElement('script');
injectScript.textContent = `
  // 这段代码在页面环境中执行,能直接拿到页面的jQuery
  const pageJQuery = window.jQuery;
  // 向GM脚本发送消息,携带jQuery对象
  window.postMessage({
    type: 'GM_GET_JQUERY',
    jquery: pageJQuery
  }, window.location.origin);
`;
document.head.appendChild(injectScript);
injectScript.remove(); // 注入后立即移除脚本标签

// 步骤2:GM脚本监听消息,接收jQuery
window.addEventListener('message', function handleJQueryMessage(event) {
  // 验证消息来源和类型,避免恶意消息
  if (event.origin !== window.location.origin || event.data.type !== 'GM_GET_JQUERY') return;
  
  const $ = event.data.jquery;
  // 现在你就可以正常使用页面的jQuery了!
  console.log('成功获取页面jQuery:', $);
  
  // 记得移除监听,避免重复接收
  window.removeEventListener('message', handleJQueryMessage);
});

这种方法完全在沙盒规则内操作,安全性更高,也能避免部分网站对unsafeWindow的限制。

关于替换unsafeWindow的通用方法

除了获取jQuery,如果你之前用unsafeWindow访问其他页面全局变量,GM4+里有两种替代思路:

  • 场景1:只读访问页面全局变量:用unsafeWindow(需加@grant unsafeWindow)或者window.wrappedJSObject(Firefox专属,无需额外权限),比如unsafeWindow.pageGlobalVar。
  • 场景2:需要和页面脚本交互:推荐用上面的postMessage方式,或者使用GM_exportFunction把GM脚本的函数暴露给页面,再让页面调用(需要@grant GM_exportFunction权限)。比如:
    // GM脚本里定义函数
    function gmFunction(data) {
      console.log('页面传来的数据:', data);
      return 'GM脚本返回的结果';
    }
    // 暴露给页面
    GM_exportFunction(gmFunction, unsafeWindow, { defineAs: 'gmFunction' });
    // 页面脚本就可以调用window.gmFunction()了
    

内容的提问来源于stack exchange,提问作者NobleUplift

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:05:35