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;
? ? ? ?}

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 背后的抽象。但我可以在代碼中清楚地看到哪些變量屬于它們所使用的函數的范圍(提高可讀性)。這首先是我的目標。
如果有人想糾正我的一些誤解,那么在我開始嘗試將其應用到我的項目之前,我們非常歡迎您的參與。
添加回答
舉報