JavaScript开关
油猴脚本详细说明:网站 JavaScript 开关(非CSP版·不影响其他脚本)
脚本信息
· 名称:网站 JavaScript 开关 (非CSP版·不影响其他脚本)
· 版本:3.0
· 作者:YourName
· 适用平台:Tampermonkey / Violentmonkey(支持油猴API的浏览器扩展)
· 匹配范围:所有网站(:///*)
· 开源:可自由修改
功能概述
本脚本允许你为每个网站独立设置是否禁用 JavaScript,就像 Via 浏览器中的“网站设定”一样。通过油猴菜单一键切换,设置后页面自动刷新,新状态立即生效。
核心特点:
· ✅ 为每个网站独立记忆 JS 启用/禁用状态(基于域名)
· ✅ 点击菜单项直接切换,无确认弹窗,自动刷新页面
· ✅ 采用非 CSP 方式禁用 JS,不影响其他油猴脚本的正常运行
· ✅ 脚本以内容脚本模式运行,不会干扰页面自身的 JavaScript 对象(如 eval、Function)
· ✅ 菜单文字实时反映当前状态(✅ 已禁用 / ❌ 已启用)
工作原理
为了在不影响其他油猴脚本的前提下尽可能阻止页面 JavaScript,脚本采用了以下技术组合:
- 删除所有 <script> 标签
· 在页面加载初期,脚本立即删除文档中所有现有的 <script> 元素(包括内联脚本和外部脚本)。
· 同时通过 MutationObserver 实时监控 DOM 变化,一旦有新的 <script> 标签被动态添加,立即将其移除。 - 移除内联事件处理器
· 遍历所有元素,删除所有以 on 开头的属性(如 onclick、onload、onerror 等),防止通过事件触发的 JavaScript 执行。 - 可选:拦截 document.write 插入脚本
· 脚本中注释了一段代码,可取消注释以阻止通过 document.write 或 document.writeln 写入包含 <script> 的内容。
· 此功能默认关闭,因为可能影响某些网站的正常渲染(但能更彻底地阻止脚本注入)。
为什么不会影响其他油猴脚本?
· 其他油猴脚本通常以内容脚本模式运行(即它们运行在独立的 JavaScript 环境中,与页面脚本隔离)。本脚本仅操作 DOM(删除节点、移除属性),不修改任何 JavaScript 内置对象(如 window.eval、Function),因此不会干扰其他脚本的独立执行空间。
· 如果其他脚本依赖页面中的某些 JavaScript 变量或函数,禁用页面 JS 后这些依赖可能失效,这是正常现象(相当于页面本身不提供这些功能)。
安装方法
- 确保浏览器已安装 Tampermonkey 或 Violentmonkey 扩展。
- 点击扩展图标,选择“创建新脚本”或“添加新脚本”。
- 将下方代码完全复制并粘贴到编辑器中,保存即可。
- 脚本将自动在所有网站上生效。
// ==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);
})();
使用方法
- 访问任意网站,点击浏览器右上角的油猴扩展图标。
- 在弹出菜单中找到本脚本的菜单项,它会显示当前网站 JS 的状态:
· ❌ 已启用 JavaScript (点击禁用):表示当前网站 JS 是开启的,点击后将会禁用。
· ✅ 已禁用 JavaScript (点击启用):表示当前网站 JS 已被禁用,点击后将会重新启用。 - 点击菜单项后,页面会自动刷新,新的设置立即生效。
- 再次访问该网站时,脚本会自动读取保存的状态,并执行相应的禁用或启用操作。
记忆功能:脚本基于域名(如 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 拦截
某些网站会通过 document.write 动态插入 <script> 标签,为彻底阻止这类情况,可取消脚本中注释掉的 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 开关”,同时最大程度兼容其他油猴脚本。如果你在使用过程中遇到问题或有改进建议,欢迎随时反馈。