这里最相关的答案并不是指 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
,如果没有声明它?这似乎完全矫枉过正。
答案 0 :(得分:3)
如果您的变量是在全局范围内声明的,那么使用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
声明忽略了块范围。
答案 1 :(得分:3)
看起来您正试图在多个位置维护角色(英雄)状态。由于每个角色的动作/状态将添加到全局变量,因此在全局范围内维护将变得越来越困难。
根据@ jeff-huijsmans的建议,我相信您应该在game
对象中保持状态。
这可以通过以下几种方式来定义:
game.state.firePaused
- 这会将您的游戏状态锁定为单个角色,但最好包含角色射击的状态。game.hero.firePaused
- 这允许每个角色保持自己的拍摄状态。这还有一个额外的好处,就是能够使用触发状态添加更多字符。顺便说一句,看起来这里的大多数答案都试图解决范围问题。全局定义变量并尝试维持函数之外的状态变得非常难以理解/读取/测试。关于这个话题会有很多意见。幸运的是,对于根本问题,您可以通过使用预先存在的状态对象来避免这种情况。
答案 2 :(得分:2)
let
与var
无关,本身就与范围有关。变量应在保持程序功能的最小范围内声明。全局变量应该是最后的手段。
因此,在您的情况下,您不需要全局变量来实现在每次函数调用时不重新声明变量的目标。您只需要创建另一个范围。由于所有代码都应该首先保留在全局范围之外,因此您的代码应该至少有一个子范围,通常使用 Immediately Invoked Function Expression 来实现,这会创建的 "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;
}
}
}
})();
答案 3 :(得分:1)
不,你不应该创建一个全局变量(而不是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`
};
}