Manifest V3 Chrome扩展同文件函数调用未定义错误解决方案
报错原因
chrome.scripting.executeScript 执行传入的函数时,会先将函数序列化,再单独注入到目标标签页的独立上下文运行,不会保留popup页面的作用域链。
你定义在popup.js中的determineResult函数仅存在于弹窗的运行环境中,被注入到网页的processPage执行时,根本无法访问到弹窗上下文内的函数、变量,因此会抛出未定义错误。
可行解决方案
你可以根据自己的代码规模选对应的实现方式:
方案1:抽离公共依赖文件统一注入
把所有需要在页面注入逻辑中复用的工具函数统一放到单独的JS文件(例如命名为inject-utils.js),注入时先加载依赖文件,再执行业务逻辑,同执行上下文内的函数可以直接互相访问。
示例代码:// inject-utils.js (放在扩展根目录) function determineResult(text) { return text; } // 其他需要复用的工具函数可以全部写在这个文件里// popup.js goButton.addEventListener("click", async () => { let [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); // 先注入公共依赖,保证工具函数在页面上下文提前声明 await chrome.scripting.executeScript({ target: { tabId: tab.id }, files: ['inject-utils.js'] }); // 再注入业务逻辑,此时可以直接访问依赖函数 chrome.scripting.executeScript({ target: { tabId: tab.id }, function: processPage, }); }); function processPage() { var result = determineResult('test'); // 正常访问,不会报错 console.log(result); }注意:
files注入的脚本和后续func注入的脚本默认处于同一个隔离世界(ISOLATED world),只要保证依赖文件注入顺序早于业务逻辑,就能正常共享上下文。方案2:将依赖逻辑整合到注入函数内部
如果复用的逻辑不多,不需要单独抽文件,可以直接把依赖函数定义在注入的执行块内部,保证执行时所有依赖都在同一个作用域:goButton.addEventListener("click", async () => { let [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); chrome.scripting.executeScript({ target: { tabId: tab.id }, func: () => { // 依赖函数直接定义在注入上下文内 function determineResult(text) { return text; } function processPage() { var result = determineResult('test'); console.log(result); } processPage(); }, }); });方案3:序列化依赖函数动态拼接注入
不想抽文件也不想重复写函数定义时,可以利用函数的toString()方法把popup上下文中的依赖函数序列化,和业务逻辑拼接后一起注入:// popup.js中定义需要复用的函数 function determineResult(text) { return text; } goButton.addEventListener("click", async () => { let [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); chrome.scripting.executeScript({ target: { tabId: tab.id }, // 动态拼接依赖声明+业务逻辑,在目标页面重新构造执行函数 func: new Function(` ${determineResult.toString()} return (${processPage.toString()})(); `) }); }); function processPage() { var result = determineResult('test'); console.log(result); }
内容的提问来源于stack exchange,提问作者darekm
相关产品推荐
相关产品推荐

