简体   繁体   English

我应该为一个不断运行的函数全局使用LET声明一个变量吗?

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

Most relevant answers here do not refer to let , which is block scoped, but to var , which is hoisted. 这里最相关的答案不是指let ,它是块作用域,而是指var ,它被挂起。 I can't seem to get a definitive answer to this. 我似乎无法得到明确的答案。

I have a variable declared globally that initializes once: 我有一个全局声明的变量初始化一次:

let firePaused = false;

and then a function in the keyboard handler that is running everytime I press a button: 然后每次按下按钮时运行的键盘处理程序中的一个函数:

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

(not relevant to the question, but it's purpose is to only allow the player to fire once, there needs to be a keyup event before they can fire again) (与问题无关,但它的目的是只允许玩家射击一次,在他们再次射击之前需要有一个keyup事件)

By the rules of clean code I should declare the variable at the top of the function... BUT that means it will be redeclared everytime I press a button. 根据清洁代码的规则,我应该在函数顶部声明变量...但这意味着每次按下按钮都会重新声明它。

It says here https://www.sitepoint.com/how-to-declare-variables-javascript/ 它在这里说https://www.sitepoint.com/how-to-declare-variables-javascript/

Initialization: When you declare a variable it is automatically initialized, which means memory is allocated for the variable by the JavaScript engine. 初始化:声明变量时,它会自动初始化,这意味着JavaScript引擎会为变量分配内存。

So I would be creating a whole new variable each time the let keyword is used. 因此,每次使用let关键字时,我都会创建一个全新的变量。

Should I go to the bother of writing a conditional at the start of the function to check if firePaused is declared yet, and if not declare it? 我是否应该在函数开始时编写一个条件来检查是否已声明firePaused ,如果没有声明它? That seems total overkill. 这似乎完全矫枉过正。

If your variable is declared in the global scope, then it doesn't really matter if you use let or var . 如果您的变量在全局范围内声明,那么使用letvar并不重要。

These are functionally identical: 这些在功能上是相同的:

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

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

The difference between var and let becomes significant when you're declaring them in blocks: 当你在块中声明它们时, varlet之间的区别变得很重要:

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

As you can see, the let declaration is restricted to its wrapping block scope. 如您所见, let声明仅限于其包装块范围。 The var declaration ignores block scope. var声明忽略块范围。

Looks like you are attempting to maintain a character's (hero) state in multiple locations. 看起来您正试图在多个位置维护角色(英雄)状态。 This will become more and more difficult to maintain in a global scope as each character's actions / states will add to the global variables. 由于每个角色的动作/状态将添加到全局变量,因此在全局范围内维护将变得越来越困难。

As per @jeff-huijsmans suggestion, I believe you should maintain the state inside your game object. 根据@ jeff-huijsmans的建议,我相信你应该保持game对象中的状态。

This could be defined in a few ways: 这可以通过以下几种方式定义:

  1. game.state.firePaused - This locks your game state to a single character, but will better contain the state of a character shooting. game.state.firePaused - 这会将你的游戏状态锁定为单个角色,但最好包含角色射击的状态。
  2. game.hero.firePaused - This allows each character to maintain their own shooting state. game.hero.firePaused - 这允许每个角色保持自己的射击状态。 This also has the added benefit of being able to add more characters with firing states. 这还有一个额外的好处,就是能够在触发状态下添加更多字符。

As an aside, it looks like most of the answers here are attempting to address the scope issue. 顺便说一句,看起来这里的大多数答案都试图解决范围问题。 Defining variables globally and attempting to maintain a state outside of a function becomes very difficult to understand/read/test. 全局定义变量并尝试维持函数之外的状态变得非常难以理解/读取/测试。 There will be a lot of opinions on this topic. 关于这个话题会有很多意见。 Fortunately for your root issue you can avoid this by using your pre-existing state object. 幸运的是,对于根本问题,您可以通过使用预先存在的状态对象来避免这种情况。

This question really has nothing to do with let vs. var , per se - it's about scope in general. 这个问题实际上与let vs. var无关 - 它本身就是范围。

Variables should be declared in the smallest scope that keeps the program functional. 应该在保持程序功能的最小范围内声明变量。 Global variables should be a last resort. 全局变量应该是最后的手段。

So, in your case, you don't need a Global variable to achieve your goal of not re-declaring the variable upon each function call. 因此,在您的情况下,您不需要Global变量来实现在每次函数调用时不重新声明变量的目标。 You just need to create another scope. 您只需要创建另一个范围。 Since all code should be kept out of the Global scope in the first place, your code should already have at least one sub-scope, which is often achieved with an Immediately Invoked Function Expression , which creates the "Module Pattern" : 由于所有代码都应该首先保留在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;
      }
    }
  }
})();

No, you should not create a global variable (and not with let anyway). 不,你不应该创建一个全局变量(而不是与let反正)。
Yes, you should declare it outside of the function if you want to have it shared between calls. 是的,如果要在调用之间共享它,则应在函数外部声明它。

You can use a closure for that, with any kind of module pattern - from ES6 module to IIFE to simple block scope. 您可以使用任何类型的模块模式 - 从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.

相关问题 我应该在函数内部还是外部声明变量? - Should I declare a variable inside a function or outside? 为什么我不能在Chrome中声明与函数体同名的let变量 - Why can't I declare a let variable with the same name as function body in Chrome 为什么我不能使用 let、const 或 var 关键字在 ES6 类中声明变量,但我可以直接声明它? - Why I can not declare a variable inside an ES6 class by using let, const or var keyword but I can declare it directly? 全局声明变量并在脚本和html代码中使用它 - To declare a variable globally and using it in script as well as html codes 如何从函数全局声明数组? - How do I declare an array from a function globally? 我应该如何在javascript中声明游标变量? - How should I declare for cursor variable in javascript? 使用“ let”通过三元运算符声明变量时出现ReferenceError - ReferenceError when using 'let' to declare variable through a ternary operator 为什么不能用 let 声明一个和 function 参数同名的变量,连参数都设置默认值? - Why can't use let to declare a variable using the same name as one function parameter, even the parameter get set default value? 当我使用“await”为 function 创建一个变量时,这个 function 会立即运行还是仅在我调用此变量时运行? - When I create a variable to a function using “await”, this function runs immediately or just when I call this variable? 有没有办法可以在 function 之外声明变量? - Is there a way that I can declare the variable outside function?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM