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

Chrome扩展:避免JavaScript重复注入的方案对比及问题排查

防止Chrome扩展内容脚本重复注入的最佳实践

我的Chrome扩展通过后台脚本执行以下代码注入injected.js:

chrome.scripting.executeScript({
    target: {tabId: tab.id},
    files: ['content/injected.js']
})

我找到了两种避免重复注入的方案:

方案1:全局标记变量(可正常运行)

基于社区方案实现的injected.js代码:

if (window.contentScriptInjected !== true) {
    window.contentScriptInjected = true; // 全局作用域标记
    const focus_event_listner = () => {
        chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
            if (message.type === "StartTimer") {
                console.log('injected.js: start timer')
            }
        });
        console.log(document.title, ": has now been injected")
    }
    focus_event_listner()
} else {
    console.log(document.title, ": was already injected")
}

方案2:检查函数定义(无法正常运行)

尝试用typeof检查函数的实现,代码无法正常工作:

if (typeof focus_event_listner === 'undefined') {
    const focus_event_listner = () => {
        chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
            if (message.type === "StartTimer") {
                console.log('injected.js: start timer')
            }
        });
        console.log(document.title, ": has now been injected")
    }
    focus_event_listner()
} else {
    console.log(document.title, ": was already injected")
}

问题解答

  1. 哪种方案更适合防止JavaScript重复注入?
    方案1是更稳妥的选择。它通过在全局window对象上设置明确的注入标记,这个标记在页面生命周期内始终可被后续注入的脚本读取,能准确判断脚本是否已执行,避免重复初始化监听逻辑、重复添加事件监听等问题。

  2. 第二种方案存在什么问题?
    核心问题出在const声明的变量作用域特性:

  • const声明的变量属于块级作用域,且没有变量提升。第一次执行脚本时,if条件判断先运行,此时focus_event_listner尚未被声明,条件成立进入代码块。但代码块内用const定义的focus_event_listner仅在该块内有效,脚本执行完毕后变量会被回收,不会暴露到全局作用域。
  • 当脚本被第二次注入时,if条件再次检查focus_event_listner的类型,发现全局作用域中依然不存在该变量,条件再次成立,导致核心逻辑被重复执行,完全起不到防重复的作用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 07:30:29