我正在开发一个 Chrome 扩展,在加载时将 JavaScript 脚本注入(inject)到事件选项卡中。我在下面附加了脚本的代码。当我使用 var 声明 myOptions 和 myGlobals 对象时,脚本运行时没有任何错误。但是如果我使用 let 来声明它们,那么我会在第一行收到语法错误,指出 myOptions 已经被声明。我什至没有在代码中的任何位置重新声明 myOptions 和 myGlobals 对象。但我试图改变它们的属性值。我无法弄清楚我哪里出了问题。我想知道为什么 let 在我的代码中不起作用?
var myOptions = {
takeNotes:false,
displayNotes:false
}
var myGlobals = {
displayingForm:false,
tabUrl:window.location.href,
notesCache:[]
}
onloadForeground();
function onloadForeground(){
chrome.storage.sync.get(myGlobals.tabUrl, (data)=>{
myGlobals.notesCache = data[myGlobals.tabUrl]?data[myGlobals.tabUrl].savedNotes:[];
console.log(data);
myGlobals.notesCache.forEach(addSticker);
});
}
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log(request);
if (request.message === "change_takeNotes_option") {
console.log(`Changing take notes option to ${request.value}`);
myOptions.takeNotes = request.value;
sendResponse({
message:"success"
});
return true;
} else if (request.message === "change_displayNotes_option") {
console.log(`Changing display notes option to ${request.value}`);
myOptions.displayNotes = request.value;
displayNotes();
sendResponse({
message:"success"
});
return true;
} else if (request.message === "save_notes_cache") {
console.log("Saved notes");
saveNotes();
sendResponse({
message:"success"
});
return true;
} else if (request.message === "reset_notes") {
console.log("Reset notes");
resetNotes();
sendResponse({
message:"success"
});
return true;
}
});
function displayNotes(){
const notes = document.getElementsByClassName("note");
console.log(notes.length);
for (let i = 0; i < notes.length; i++) {
notes[i].style.visibility = (myOptions.displayNotes)?"visible":"hidden";
}
}
function saveNotes() {
if (myGlobals.notesCache.length > 0) {
chrome.storage.sync.set({[myGlobals.tabUrl]: {savedNotes:myGlobals.notesCache}});
} else {
chrome.storage.sync.remove(myGlobals.tabUrl);
}
}
function displayForm() {
myGlobals.displayingForm = true;
}
function discardForm() {
setTimeout(() => {
myGlobals.displayingForm = false;
}, 500);
}
function addNote(){
console.log("Adding note");
let noteTitle = document.getElementById("note-inputTitle").value;
let noteDescription = document.getElementById("note-inputDescription").value;
if (noteTitle == null || noteTitle.trim() === "") {
alert("The note requires a title");
} else if (noteDescription == null || noteDescription.trim() === "") {
alert("The note requires a description");
} else {
let note = {
title: noteTitle,
description: noteDescription,
}
myGlobals.notesCache.push(note);
console.log("Current note cache");
console.log(myGlobals.notesCache);
discardForm();
}
}
function discardNote(index) {
myGlobals.displayingForm=true;
setTimeout(()=>{
myGlobals.displayingForm=false;
}, 300);
console.log("Discarding note " + index);
myGlobals.notesCache.splice(index, 1);
console.log("Current note cache");
console.log(myGlobals.notesCache);
}
function resetNotes(){
myGlobals.notesCache = [];
console.log(notesCache);
}
这是我用来注入(inject)上述脚本的后台脚本
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
console.log(changeInfo);
if (changeInfo.status === "complete" && /^http/.test(tab.url)) {
chrome.scripting.insertCSS({
target: {
tabId: tabId
},
files: ["./foreground.css"]
})
chrome.scripting.executeScript({
target: {
tabId: tabId
},
files: ["./foreground.js"]
})
.then(() => {
console.log("Injected foreground script " + tabId);
chrome.storage.sync.set({ [tabId]: { options:{takeNotes:false, displayNotes:false} } });
})
.catch(err => {
console.log(err);
});
}
});
最佳答案
您在同一页面上使用了两次executeScript
,因此当注入(inject)的脚本再次运行时,它会尝试在同一上下文中声明一个let
变量,但这是被禁止的JavaScript 规范。
解决方案:
继续使用
var
将代码包装在 IIFE 中:
(() => { // your entire code here })()
不要通过在executeScript之前添加条件来重新注入(inject)脚本两次,例如您可以“ping”该选项卡:
// injected file chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { if (msg === 'ping') sendResponse(true); });
// background or popup script function inject(tabId) { chrome.tabs.sendMessage(tabId, 'ping', {frameId: 0}, () => { if (chrome.runtime.lastError) { // ManifestV2: chrome.tabs.executeScript(tabId, {file: 'content.js'}); // ManifestV3: // chrome.scripting.executeScript({target: {tabId}, file: 'content.js'}); } }); }
关于javascript - 未捕获的语法错误 : Identifier 'myOptions' has already been declared in JavaScript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68432014/