簡體   English   中英

我應該為一個不斷運行的函數全局使用LET聲明一個變量嗎?

[英]Should I declare a variable using LET globally for a function that runs constantly?

這里最相關的答案不是指let ,它是塊作用域,而是指var ,它被掛起。 我似乎無法得到明確的答案。

我有一個全局聲明的變量初始化一次:

let firePaused = false;

然后每次按下按鈕時運行的鍵盤處理程序中的一個函數:

function actOnKeyPress() {
  if (rightPressed) {
    game.hero.rotate(game.hero.speed);
  } else if (leftPressed) {
    game.hero.rotate(-game.hero.speed);
  }
  if (!firePressed) {
    firePaused = false;
  }
  if (firePressed && options.numberOfBullets > 0) {
    if (!firePaused) {
      fireBullet();
      firePaused = true;
    }
  }
}

(與問題無關,但它的目的是只允許玩家射擊一次,在他們再次射擊之前需要有一個keyup事件)

根據清潔代碼的規則,我應該在函數頂部聲明變量...但這意味着每次按下按鈕都會重新聲明它。

它在這里說https://www.sitepoint.com/how-to-declare-variables-javascript/

初始化:聲明變量時,它會自動初始化,這意味着JavaScript引擎會為變量分配內存。

因此,每次使用let關鍵字時,我都會創建一個全新的變量。

我是否應該在函數開始時編寫一個條件來檢查是否已聲明firePaused ,如果沒有聲明它? 這似乎完全矯枉過正。

如果您的變量在全局范圍內聲明,那么使用letvar並不重要。

這些在功能上是相同的:

 let myVar = 123; function doStuff() { console.log(myVar); } doStuff(); 

 var myVar = 123; function doStuff() { console.log(myVar); } doStuff(); 

當你在塊中聲明它們時, varlet之間的區別變得很重要:

 if(true) { var foo = 1; } if(true) { let bar = 2; } console.log("var foo:", foo); console.log("let bar:", bar); 

如您所見, let聲明僅限於其包裝塊范圍。 var聲明忽略塊范圍。

看起來您正試圖在多個位置維護角色(英雄)狀態。 由於每個角色的動作/狀態將添加到全局變量,因此在全局范圍內維護將變得越來越困難。

根據@ jeff-huijsmans的建議,我相信你應該保持game對象中的狀態。

這可以通過以下幾種方式定義:

  1. game.state.firePaused - 這會將你的游戲狀態鎖定為單個角色,但最好包含角色射擊的狀態。
  2. game.hero.firePaused - 這允許每個角色保持自己的射擊狀態。 這還有一個額外的好處,就是能夠在觸發狀態下添加更多字符。

順便說一句,看起來這里的大多數答案都試圖解決范圍問題。 全局定義變量並嘗試維持函數之外的狀態變得非常難以理解/讀取/測試。 關於這個話題會有很多意見。 幸運的是,對於根本問題,您可以通過使用預先存在的狀態對象來避免這種情況。

這個問題實際上與let vs. var無關 - 它本身就是范圍。

應該在保持程序功能的最小范圍內聲明變量。 全局變量應該是最后的手段。

因此,在您的情況下,您不需要Global變量來實現在每次函數調用時不重新聲明變量的目標。 您只需要創建另一個范圍。 由於所有代碼都應該首先保留在Global范圍之外,因此您的代碼應該至少有一個子范圍,這通常通過立即調用的函數表達式實現,該表達式創建“模塊模式”

(function(){
  let firePaused = false; // This is scoped to the entire module, but not Global

  function actOnKeyPress() {
    if (rightPressed) {
      game.hero.rotate(game.hero.speed);
    } else if (leftPressed) {
      game.hero.rotate(-game.hero.speed);
    }
    if (!firePressed) {
      firePaused = false;
    }
    if (firePressed && options.numberOfBullets > 0) {
      if (!firePaused) {
        fireBullet();
        firePaused = true;
      }
    }
  }
})();

不,你不應該創建一個全局變量(而不是與let反正)。
是的,如果要在調用之間共享它,則應在函數外部聲明它。

您可以使用任何類型的模塊模式 - 從ES6模塊到IIFE到簡單的塊范圍。

// ES6 module
let firePaused = false;
export function actOnKeyPress() {
  // use `firePaused`
}

// IIFE
var actOnKeyPress = (function() {
  let firePaused = false;
  return function actOnKeyPress() {
    // use `firePaused`
  };
}());

// block scope
var actOnKeyPress;
{
  let firePaused = false;
  actOnKeyPress = function actOnKeyPress() {
    // use `firePaused`
  };
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM