本文目录导读:

- 浏览器用户脚本(Tampermonkey / Greasemonkey 等)
- Node.js 模块
- 浏览器扩展(Chrome/Firefox)
- 通用的清理原则
- 如果脚本没有提供清理功能(最坏情况)
- 总结:最好的清理是“设计时考虑清理”
在脚本环境中,“卸载脚本”通常指移除脚本加载的全局变量、事件监听、定时器、DOM元素修改等副作用,要“清理干净”,需要根据脚本的类型(如用户脚本、Node.js模块、浏览器扩展等)采取不同的策略,以下是几种常见场景的清理方法:
浏览器用户脚本(Tampermonkey / Greasemonkey 等)
用户脚本通常通过 @grant 声明权限,要完全清理卸载,需要还原脚本所做的所有修改。
脚本内部应提供卸载函数:
// ==UserScript==
// @name My Script
// @grant GM_addStyle
// @grant GM_registerMenuCommand
// ==/UserScript==
// 存储所有副作用,便于卸载清理
const cleanups = [];
// 示例1: 添加全局样式
const style = GM_addStyle('.my-script-style { color: red; }');
cleanups.push(() => style.remove());
// 示例2: 添加事件监听
const handler = () => console.log('clicked');
document.addEventListener('click', handler);
cleanups.push(() => document.removeEventListener('click', handler));
// 示例3: 设置定时器
const timer = setInterval(() => {}, 1000);
cleanups.push(() => clearInterval(timer));
// 示例4: 修改DOM(需记录原始状态)
const originalContent = document.body.innerHTML;
cleanups.push(() => { document.body.innerHTML = originalContent; });
// 卸载函数
window.myScriptCleanup = function() {
cleanups.forEach(fn => fn());
cleanups.length = 0; // 清空数组
console.log('Script cleaned up');
};
// 在菜单中添加卸载命令(如果支持)
GM_registerMenuCommand('Uninstall Script', () => {
window.myScriptCleanup();
});
手动清理:如果脚本没有提供卸载函数,需要手动检查并移除:
- 检查
document.head中是否有脚本注入的<style>或<link>。 - 移除脚本添加的全局变量(如
window.myScriptData)。 - 清空定时器(通过
console.log或开发者工具查看setInterval的ID)。 - 移除事件监听(在开发者工具的 Event Listeners 面板中查找)。
Node.js 模块
Node.js 中卸载模块通常指从 require.cache 中清除,并释放其副作用(如全局变量、定时器、数据库连接等)。
模块内部清理:
// my-module.js
let timer;
module.exports = {
start() {
timer = setInterval(() => {}, 1000);
},
// 提供清理方法
cleanup() {
clearInterval(timer);
// 关闭数据库连接、文件描述符等
console.log('Module cleaned up');
}
};
外部强制卸载:
// 强制从缓存中删除模块
const modulePath = require.resolve('./my-module.js');
delete require.cache[modulePath];
// 但模块内的定时器仍然存在!需要手动调用清理
const myModule = require('./my-module.js');
myModule.cleanup();
更好的做法:使用 process.on('exit') 或 process.on('SIGINT') 自动清理:
process.on('exit', () => {
clearInterval(timer);
// 其他清理
});
浏览器扩展(Chrome/Firefox)
扩展卸载时,浏览器会自动清理大部分副作用(如后台页面、内容脚本),但持久化数据(如 chrome.storage、IndexedDB、Cookies)不会被自动清除。
清理持久化数据:
-
在扩展的
background.js中添加卸载监听:// 监听扩展被卸载(仅 Chrome 支持) chrome.runtime.onSuspend.addListener(() => { // 清理存储 chrome.storage.local.clear(); // 清理 IndexedDB indexedDB.deleteDatabase('MyDB'); // 清理 Cookies(需指定域名) chrome.cookies.remove({ url: 'https://example.com', name: 'session' }); }); -
或者让用户手动清除:在扩展选项中提供“清除所有数据”按钮。
通用的清理原则
无论哪种脚本,清理都应该遵循以下步骤:
- 记录所有副作用:在脚本初始运行时,保存所有被修改的状态、创建的对象、注册的回调。
- 提供反函数:每个副作用都对应一个还原操作(如
addEventListener→removeEventListener,setTimeout→clearTimeout)。 - 提供统一的清理接口:如
cleanup()、destroy()或全局变量__cleanup__。 - 事件监听器:使用有名字的函数(不要用匿名函数)以便移除。
- 定时器:保存所有定时器ID,统一
clearInterval/clearTimeout。 - DOM修改:如果修改了很多内容,最好在开始时保存一份原始 DOM 快照(
document.body.cloneNode(true)),清理时恢复。
如果脚本没有提供清理功能(最坏情况)
- 对于用户脚本:禁用或卸载该脚本(在Tampermonkey中点击“移除”),然后刷新页面——大部分副作用会随页面重载消失。
- 对于Node.js:关闭进程(
Ctrl+C),所有定时器和监听器都会随进程终止。 - 对于浏览器扩展:在
chrome://extensions中移除扩展,刷新所有受影响页面。
最好的清理是“设计时考虑清理”
- 写脚本时:始终提供
cleanup()函数,并遵循“副作用记录+反向操作”模式。 - 卸载时:优先调用脚本提供的清理函数,然后刷新页面或重启进程。
- 持久数据:需要手动删除存储(存储、数据库、cookies)。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播