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

萝らか妹 提交于 2021-01-28 04:27:43

问题


Most relevant answers here do not refer to let, which is block scoped, but to var, which is hoisted. 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)

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/

Initialization: When you declare a variable it is automatically initialized, which means memory is allocated for the variable by the JavaScript engine.

So I would be creating a whole new variable each time the let keyword is used.

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? That seems total overkill.


回答1:


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.

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.
  2. game.hero.firePaused - This allows each character to maintain their own shooting state. 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.




回答2:


If your variable is declared in the global scope, then it doesn't really matter if you use let or var.

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:

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. The var declaration ignores block scope.




回答3:


This question really has nothing to do with let vs. var, per se - it's about scope in general.

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. 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":

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



回答4:


No, you should not create a global variable (and not with let anyway).
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 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`
  };
}


来源:https://stackoverflow.com/questions/50136998/should-i-declare-a-variable-using-let-globally-for-a-function-that-runs-constant

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!