javascript - 未捕获的语法错误 : Identifier 'myOptions' has already been declared in JavaScript

标签 javascript google-chrome-extension syntax-error

我正在开发一个 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 规范。

解决方案:

  1. 继续使用var

  2. 将代码包装在 IIFE 中:

    (() => {
    // your entire code here
    })()
    
  3. 不要通过在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/

相关文章:

javascript - 使用 velocity.js 将 div 动画化到中心?

javascript - 单击链接时显示加载(除了 ctrl+click)

google-chrome - 在 Firefox/Chrome 扩展程序中使用 Java/Python 库

javascript - 创建 Javascript 对象时出错

java - 在 Java 整数上,Character.IsDigit 返回 false 而不是 true

javascript - var x = x || {};与 x = window.x || {};

javascript - jQuery CSS 到纯 Javascript

javascript - 在 Chrome 扩展程序中动态部署内容脚本

javascript - 获取文本框的输入类型

php - 解析错误: syntax error, unexpected '$_POST' (T_VARIABLE) error and i just cant understand why?