繁体   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