亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

JS| 訪問該對象的函數多次運行后,初始化對象未定義

JS| 訪問該對象的函數多次運行后,初始化對象未定義

一只名叫tom的貓 2023-09-21 10:48:56
我正在嘗試減少 Chrome 擴展中的全局變量,以減少 JavaScript 中的“意大利面”或歧義。我試圖通過一個 init 函數來嘗試此操作,該函數在 mousedown eventListener 回調函數中聲明這些全局變量,該函數可能會被多次觸發。這樣我就可以將這些變量+事件作為此類回調的參數傳遞給其他 eventListener 回調(即 mouseup 回調)。我已將問題分解為一個單獨的文件:索引.html<!doctype html><html><head>  <meta charset="utf-8"></head><body>  <script src="test.js"></script></body></html>測試.jsisVarsInitOnce = false;function executesMoreThanOnce() {    const initVariables = function() {        console.log('runs once');        const bools = {            boolOne: false,            boolTwo: false,            boolThree: false        };        const events = {            clickEvent:                function(event) {                    //do stuff                },            keyEvent:                function(event) {                    //do other stuff                }        };        return {            bools: bools,            events: events        }    };    if (!isVarsInitOnce) {        isVarsInitOnce = true;        let vars = initVariables();        var booleanObject = vars.bools;        var eventObject = vars.events;    }    console.log('objects: ', booleanObject, eventObject);    //attempting to access initialised variable after function is executed more than once will cause an error.    //this is because the booleanObject is now undefined.    booleanObject.boolOne = true;}//runs twicefor (let i=0; i<2; i++) {    executesMoreThanOnce();}我用來控制執行的方法initVariables()是一個全局布爾變量,isVarsInitOnce它可以有效地初始化變量并設置executesMoreThanOnce()一次在函數中使用的對象??梢栽谘h中調用該函數的第一個實例中訪問這些for對象,但是undefined當嘗試在循環中調用該函數的第二個實例中訪問這些對象時,就會訪問這些對象for。這在控制臺輸出中非常清楚地表示出來:runs oncetest.js:38 objects:  {boolOne: false, boolTwo: false, boolThree: false} {clickEvent: ?, keyEvent: ?}test.js:38 objects:  undefined undefined //<--- (function called 2nd time)test.js:42 Uncaught TypeError: Cannot set property 'boolOne' of undefined    at executesMoreThanOnce (test.js:42)    at test.js:47我不確定為什么會發生這種情況。誰能幫助我理解為什么這不能正常工作?對于我的情況,有人有更好的建議來減少全局變量嗎?非常感謝。
查看完整描述

2 回答

?
紅糖糍粑

TA貢獻1815條經驗 獲得超6個贊

首先,booleanObject 和 eventObject 都需要在 if 語句之外聲明才能處于作用域內。其次,如果您需要多次運行executesMoreThanOnce,則需要在for循環中將isVarsInitOnce設置為false


? ? ? ? ? ?let? isVarsInitOnce = false;

? ? ? ? ? ?

function executesMoreThanOnce() {

? ? const initVariables = function() {

? ? ? ? console.log('runs once');


? ? ? ? const bools = {

? ? ? ? ? ? boolOne: false,

? ? ? ? ? ? boolTwo: false,

? ? ? ? ? ? boolThree: false

? ? ? ? };


? ? ? ? const events = {

? ? ? ? ? ? clickEvent:

? ? ? ? ? ? ? ? function(event) {

? ? ? ? ? ? ? ? ? ? //do stuff

? ? ? ? ? ? ? ? },

? ? ? ? ? ? keyEvent:

? ? ? ? ? ? ? ? function(event) {

? ? ? ? ? ? ? ? ? ? //do other stuff

? ? ? ? ? ? ? ? }

? ? ? ? };


? ? ? ? return {

? ? ? ? ? ? bools: bools,

? ? ? ? ? ? events: events

? ? ? ? }

? ? };

? ? ? let booleanObject ; // declaring booleanObject outside the if statement

? ? ? ? let eventObject ; // declaring eventObject outside the if statement

? ? if (!isVarsInitOnce) {

? ? ? ? isVarsInitOnce = true;

? ? ? ? let vars = initVariables();


? ? ? ? booleanObject = vars.bools;

? ? ? ? eventObject = vars.events;

? ? }


? ? console.log('objects: ', booleanObject, eventObject);


? ? //attempting to access initialised variable after function is executed more than once will cause an error.

? ? //this is because the booleanObject is now undefined.

? ? booleanObject.boolOne = true;

}


//runs 5 times

for (let i=0; i<5; i++) {// Will execute 5 times

? ? executesMoreThanOnce();

? ? isVarsInitOnce = false;

}

編輯


抱歉,我的錯,我沒有完全理解您的要求。查看以下內容:


JavaScript


? ? // This will be the object that holds your variables

? ? ?let vars;

? ? ? ?

? ? ? ?function executesMoreThanOnce(obj) {

? ? ? ? ? ?const initVariables = function(obj) {

? ? ? ? ? ? ??

? ? ? ? ? ? ? ?console.log('runs once and obj = ' + obj);

? ? ? ? ? ? ? ?if (obj == undefined) {

? ? ? ? ? ? ? ??

? ? ? ? ? ? ? ? console.log('initialize once');

? ? ? ? ? ? ? ? ? ? const bools = {

? ? ? ? ? ? ? ? ? ? ? ? boolOne: false,

? ? ? ? ? ? ? ? ? ? ? ? boolTwo: false,

? ? ? ? ? ? ? ? ? ? ? ? boolThree: false

? ? ? ? ? ? ? ? ? ? };

? ? ? ? ? ??

? ? ? ? ? ? ? ? ? ? const events = {

? ? ? ? ? ? ? ? ? ? ? ? clickEvent:

? ? ? ? ? ? ? ? ? ? ? ? ? ? function(event) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //do stuff

? ? ? ? ? ? ? ? ? ? ? ? ? ? },

? ? ? ? ? ? ? ? ? ? ? ? keyEvent:

? ? ? ? ? ? ? ? ? ? ? ? ? ? function(event) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //do other stuff

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? };

? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ?return (function(){

? ? ? ? ? ? ? ? ? ? ? ? return {bools: bools,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? events: events};

? ? ? ? ? ? ? ? ? ? })();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? // If vars object, "which we passed as argument", is initialized once before just return it

? ? ? ? ? ? ? ? return vars;

? ? ? ? ? ? ? ?

? ? ? ? ? ?};


? ? ? ? ? ?vars = initVariables(vars);

? ? ? ? ? ? ? ?

? ? ? ? ? ?let? ? booleanObject = vars.bools;

? ? ? ? ? ?let? ? eventObject = vars.events;

? ? ? ? ? ? ? ?

? ? ? ? ? ?

? ? ? ?

? ? ? ? ? ?console.log('objects: ', booleanObject, eventObject);

? ? ? ?

? ? ? ? ? ?//attempting to access initialised variable after function is executed more than once will cause an error.

? ? ? ? ? ?//this is because the booleanObject is now undefined.

? ? ? ? ? ?// Yes you can now access the variables

? ? ? ? ? ?booleanObject.boolOne = true;

? ? ? ?}

? ? ? ?

? ? ? ?//runs 5 times

? ? ? ?for (let i=0; i<5; i++) {// Will execute 5 times

? ? ? ? ? ? // Removed the bool flag and now passing the vars object as argument

? ? ? ? ? ?executesMoreThanOnce(vars);

? ? ? ? ??

? ? ? ? ? ?//executesMoreThanOnce();

? ? ? ? ? ?//isVarsInitOnce = false;

? ? ? ?}


查看完整回答
反對 回復 2023-09-21
?
肥皂起泡泡

TA貢獻1829條經驗 獲得超6個贊

我看過一些關于 JS 中的作用域和閉包的閱讀,我想我已經找到了原始問題中分解問題的解決方案。


Aber Abou-Rahma 給出的答案并沒有解決我的問題,因為每次調用executesMoreThanOnce().


這不是我想要的,因為我只想在調用該函數的第一個實例中初始設置變量(因為在我的實際項目中,該函數executesMoreThanOnce()本質上代表一個單擊事件回調,需要在事件發生時保留數據)被重新觸發)。


我的解決方案使用立即調用函數表達式 (IIFE)。在 IIFE 范圍內本地初始化變量,并在其返回的get方法中將變量釋放到全局范圍:


測試.js


const TEST = (function() {

    let booleans = {

        boolOne: false,

        boolTwo: false,

        boolThree: false

    };


    let events = {

        clickEvent:

            function(event) {

                //do stuff

            },

        keyEvent:

            function(event) {

                //do other stuff

            }

    };


    return {

        executesMoreThanOnce: function(booleans, events, index) {

            booleanObject = booleans;

            eventsObject = events;


            if (i == 2) {

                booleanObject.boolTwo = true;

            }

            else if (i == 4) {

                booleanObject.boolOne = true;

                booleanObject.boolTwo = false;

            }


            console.log('booleanObject: ', booleanObject);

        },

        get variables() {

            return {

                booleans,

                events

            }

        }

    };

}());


for (var i=0; i<5; i++) {

    TEST.executesMoreThanOnce(TEST.variables.booleans, TEST.variables.events, i);

}

您現在可以在控制臺中看到該TEST.executesMoreThanOnce()函數開始使用 IIFE 函數中本地定義的初始變量TEST:


i = 0 | booleanObject:  {boolOne: false, boolTwo: false, boolThree: false}

i = 1 | booleanObject:  {boolOne: false, boolTwo: false, boolThree: false}

i = 2 | booleanObject:  {boolOne: false, boolTwo: true, boolThree: false}

i = 3 | booleanObject:  {boolOne: false, boolTwo: true, boolThree: false}

i = 4 | booleanObject:  {boolOne: true, boolTwo: false, boolThree: false}

我們現在還可以看到,一旦 i 值滿足函數中的某些條件TEST.executesMoreThanOnce(),布爾值就開始切換,但更重要的是,這些變化在函數調用之間持續存在。


我仍然不確定我是否完全理解 IIFE 背后的抽象。但我可以在代碼中清楚地看到哪些變量屬于它們所使用的函數的范圍(提高可讀性)。這首先是我的目標。


如果有人想糾正我的一些誤解,那么在我開始嘗試將其應用到我的項目之前,我們非常歡迎您的參與。


查看完整回答
反對 回復 2023-09-21
  • 2 回答
  • 0 關注
  • 127 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號