Должен ли я объявить переменную, используя LET глобально для функции, которая работает постоянно? - PullRequest
0 голосов
/ 02 мая 2018

Наиболее релевантные ответы здесь относятся не к 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, а если нет, то объявить его? Это кажется полным перебором.

Ответы [ 4 ]

0 голосов
/ 02 мая 2018

Похоже, вы пытаетесь сохранить состояние персонажа (героя) в нескольких местах. Это будет все труднее поддерживать в глобальной области видимости, поскольку действия / состояния каждого персонажа будут добавлять к глобальным переменным.

Согласно совету @ jeff-huijsmans, я считаю, что вы должны поддерживать состояние внутри вашего game объекта.

Это можно определить несколькими способами:

  1. game.state.firePaused - Это блокирует ваше игровое состояние для одного персонажа, но лучше будет содержать состояние стрельбы персонажа.
  2. game.hero.firePaused - Это позволяет каждому персонажу поддерживать свое собственное состояние стрельбы. Это также имеет дополнительное преимущество, заключающееся в возможности добавлять больше персонажей с состояниями стрельбы.

Кроме того, похоже, что большинство ответов здесь пытаются решить проблему объема. Определение глобальных переменных и попытка сохранить состояние вне функции становится очень трудным для понимания / чтения / тестирования. По этой теме будет много мнений. К счастью для вашей корневой проблемы, вы можете избежать этого, используя уже существующий объект состояния.

0 голосов
/ 02 мая 2018

Нет, вам не следует создавать глобальную переменную (и в любом случае не с 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`
  };
}
0 голосов
/ 02 мая 2018

Этот вопрос на самом деле не имеет ничего общего с let против var, как таковой - речь идет о сфере действия в целом.

Переменные должны быть объявлены в наименьшем объеме, который поддерживает работоспособность программы. Глобальные переменные должны быть последним средством.

Итак, в вашем случае вам не нужна глобальная переменная, чтобы достичь цели не объявлять переменную при каждом вызове функции. Вам просто нужно создать еще одну область. Поскольку весь код должен быть в первую очередь исключен из глобальной области видимости, в вашем коде уже должна быть хотя бы одна под-область, что часто достигается с помощью выражения немедленного вызова функции , который создает «Шаблон модуля» :

(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;
      }
    }
  }
})();
0 голосов
/ 02 мая 2018

Если ваша переменная объявлена ​​в глобальной области видимости, тогда не имеет значения, используете ли вы let или var.

Они функционально идентичны:

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

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

Разница между var и let становится значительной, когда вы объявляете их в блоках:

if(true) {
  var foo = 1;
}
if(true) {
  let bar = 2;
}

console.log("var foo:", foo);
console.log("let bar:", bar);

Как видите, объявление let ограничено областью его действия. В объявлении var игнорируется область блока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...