油猴脚本详细说明:网站 JavaScript 开关(非CSP版·不影响其他脚本)
脚本信息
· 名称:网站 JavaScript 开关 (非CSP版·不影响其他脚本) · 版本:3.0 · 作者:YourName · 适用平台:Tampermonkey / Violentmonkey(支持油猴API的浏览器扩展) · 匹配范围:所有网站(:///*) · 开源:可自由修改
功能概述
本脚本允许你为每个网站独立设置是否禁用 JavaScript,就像 Via 浏览器中的“网站设定”一样。通过油猴菜单一键切换,设置后页面自动刷新,新状态立即生效。
核心特点:
· ✅ 为每个网站独立记忆 JS 启用/禁用状态(基于域名) · ✅ 点击菜单项直接切换,无确认弹窗,自动刷新页面 · ✅ 采用非 CSP 方式禁用 JS,不影响其他油猴脚本的正常运行 · ✅ 脚本以内容脚本模式运行,不会干扰页面自身的 JavaScript 对象(如 eval、Function) · ✅ 菜单文字实时反映当前状态(✅ 已禁用 / ❌ 已启用)
工作原理
为了在不影响其他油猴脚本的前提下尽可能阻止页面 JavaScript,脚本采用了以下技术组合:
为什么不会影响其他油猴脚本?
· 其他油猴脚本通常以内容脚本模式运行(即它们运行在独立的 JavaScript 环境中,与页面脚本隔离)。本脚本仅操作 DOM(删除节点、移除属性),不修改任何 JavaScript 内置对象(如 window.eval、Function),因此不会干扰其他脚本的独立执行空间。 · 如果其他脚本依赖页面中的某些 JavaScript 变量或函数,禁用页面 JS 后这些依赖可能失效,这是正常现象(相当于页面本身不提供这些功能)。
安装方法
// ==UserScript==
// @name 网站 JavaScript 开关 (非CSP版·不影响其他脚本)
// @namespace http://tampermonkey.net/
// @version 3.0
// @description 为每个网站独立开关 JavaScript,通过删除脚本标签和事件处理器实现,不影响其他油猴脚本。点击菜单切换后自动刷新。
// @author YourName
// @match *://*/*
// @run-at document-start
// @grant GM_registerMenuCommand
// @grant GM_getValue
// @grant GM_setValue
// @all-frames true
// ==/UserScript==
(function() {
'use strict';
const currentHost = location.hostname;
const STORAGE_KEY = 'js_disabled_' + currentHost;
let isDisabled = GM_getValue(STORAGE_KEY, false);
// ---------- 禁用 JavaScript 的非CSP方法 ----------
function disableJavaScript() {
// 1. 删除所有现有 <script> 标签
function removeAllScripts() {
document.querySelectorAll('script').forEach(script => script.remove());
}
// 2. 移除元素的内联事件处理器 (如 onclick, onload 等)
function removeInlineEventHandlers(root) {
const allElements = root.querySelectorAll ? root.querySelectorAll('*') : [];
allElements.forEach(el => {
const attrs = el.attributes;
if (!attrs) return;
for (let i = attrs.length - 1; i >= 0; i--) {
const attrName = attrs[i].name;
if (attrName.length > 2 && attrName.toLowerCase().startsWith('on')) {
el.removeAttribute(attrName);
}
}
});
}
// 3. 监听动态添加的节点,及时清理脚本和事件
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === 1 && node.tagName === 'SCRIPT') {
node.remove();
}
if (node.nodeType === 1 && node.querySelectorAll) {
node.querySelectorAll('script').forEach(script => script.remove());
removeInlineEventHandlers(node);
}
});
});
});
if (document.documentElement) {
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
}
// 立即执行一次清理
if (document.documentElement) {
removeAllScripts();
removeInlineEventHandlers(document.documentElement);
} else {
const rootObserver = new MutationObserver(() => {
if (document.documentElement) {
removeAllScripts();
removeInlineEventHandlers(document.documentElement);
rootObserver.disconnect();
}
});
rootObserver.observe(document, { childList: true, subtree: true });
}
// 可选:阻止通过 document.write 插入脚本(默认关闭,需要请取消注释)
/*
const originalWrite = document.write;
const originalWriteln = document.writeln;
document.write = function(...args) {
const str = args.join('');
if (str.includes('<script')) {
console.warn('阻止了包含脚本的 document.write');
return;
}
return originalWrite.apply(this, args);
};
document.writeln = function(...args) {
const str = args.join('');
if (str.includes('<script')) {
console.warn('阻止了包含脚本的 document.writeln');
return;
}
return originalWriteln.apply(this, args);
};
*/
}
if (isDisabled) {
disableJavaScript();
}
// ---------- 菜单命令:切换状态并自动刷新 ----------
function toggleJS() {
const newState = !isDisabled;
GM_setValue(STORAGE_KEY, newState);
location.reload();
}
const menuText = isDisabled ? '✅ 已禁用 JavaScript (点击启用)' : '❌ 已启用 JavaScript (点击禁用)';
GM_registerMenuCommand(menuText, toggleJS);
})();
使用方法
记忆功能:脚本基于域名(如 example.com)保存设置,不同网站的设置互不干扰。即使关闭浏览器,下次访问时设置仍然有效。
注意事项
· 刷新页面:切换设置后页面会自动刷新,这是必要的,因为禁用 JS 必须在页面加载初期执行。自动刷新无确认弹窗。 · 与其他脚本的兼容性:本脚本不会干扰其他油猴脚本的加载和执行,但其他脚本如果依赖页面提供的 JavaScript 功能(例如页面中的某个全局变量),则可能因 JS 被禁用而失效。这是预期行为,相当于浏览器原生关闭 JS 的效果。 · 无法完全阻止所有 JS 执行: · 通过 javascript: 伪协议(如 a 标签的 href="javascript:...")仍然可能触发 JS,但现代网站极少使用。 · 通过 eval 或 new Function 动态生成的代码未被阻止(本脚本有意避免覆盖这些函数以保护其他脚本)。大多数网站不依赖此类方式,如有需要可自行扩展。 · iframe 支持:脚本默认对所有框架生效(@all-frames true),可以阻止内嵌框架中的 JS。 · 网站渲染问题:禁用 JS 后,部分依赖 JS 进行渲染或跳转的网站可能出现布局错乱、白屏或无法交互,这是禁用 JS 的正常现象。
自定义与高级选项
如果只想对特定网站生效,可以修改 @match 行,例如:
// @match *://example.com/*
// @match *://*.example.org/*
某些网站会通过 document.write 动态插入 [removed] 标签,为彻底阻止这类情况,可取消脚本中注释掉的 document.write 覆写代码(删除 /* 和 */)。但请注意,这可能会破坏部分依赖 document.write 的正常网站。
修改 menuText 变量即可改变菜单显示的文字,例如去掉表情符号或改为其他语言。
如果需要阻止 javascript: 伪协议链接,可以在脚本中添加以下代码(放在 disableJavaScript 函数内):
document.addEventListener('click', function(e) {
let target = e.target.closest('a');
if (target && target.href && target.href.startsWith('javascript:')) {
e.preventDefault();
}
}, true);
此代码会阻止点击 javascript: 链接执行 JS。
常见问题解答
Q:为什么我点击菜单后没有反应? A:请检查 Tampermonkey 是否正常运行,并且脚本已启用。尝试重新安装或刷新页面。
Q:禁用 JS 后,其他油猴脚本还能运行吗? A:可以,本脚本不会阻止其他内容脚本的加载和执行。但其他脚本如果依赖页面 JS 提供的变量/函数,可能会报错,这是正常的。
Q:设置会保存在哪里?清除浏览器缓存会丢失吗? A:设置通过 GM_setValue 保存在 Tampermonkey 的存储中,独立于浏览器缓存。清除缓存不会影响设置,但卸载脚本或清除扩展数据会导致设置丢失。
Q:能否全局禁用 JS,而不是逐个网站设置? A:本脚本设计为按网站独立设置。如需全局禁用,可修改脚本,将 isDisabled 固定为 true 并删除存储逻辑,但这样会失去灵活性。
Q:为什么不用 CSP(内容安全策略)? A:早期版本使用 CSP,但发现 CSP 会影响某些以 @grant none 运行的油猴脚本(这类脚本直接注入页面)。为避免影响其他脚本,改用 DOM 清理方案。
Q:脚本会导致某些网站无法正常工作吗? A:是的,禁用 JS 本身就是为了阻止网站脚本执行,因此依赖 JS 的网站功能将失效。这是预期结果,而非脚本 Bug。
版本历史
· 3.0:采用非 CSP 方案,避免影响其他油猴脚本;移除弹窗确认,自动刷新;清理内联事件处理器。 · 2.x:CSP 版本(已弃用)。 · 1.x:基础功能版本。
结语
本脚本提供了一个轻量、便捷的方式来模拟 Via 浏览器的“网站 JavaScript 开关”,同时最大程度兼容其他油猴脚本。如果你在使用过程中遇到问题或有改进建议,欢迎随时反馈。