Javascript 我应该为一个经常运行的函数使用LET全局声明一个变量吗?
这里最相关的答案不是指块范围的let,而是指挂起的var。我似乎无法得到一个明确的答案 我有一个全局声明的变量,初始化一次:Javascript 我应该为一个经常运行的函数使用LET全局声明一个变量吗?,javascript,ecmascript-6,Javascript,Ecmascript 6,这里最相关的答案不是指块范围的let,而是指挂起的var。我似乎无法得到一个明确的答案 我有一个全局声明的变量,初始化一次: let firePaused = false; 然后是键盘处理程序中的一个函数,每次我按下按钮时都会运行该函数: function actOnKeyPress() { if (rightPressed) { game.hero.rotate(game.hero.speed); } else if (leftPressed) { game.hero
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;
}
}
}
(与问题无关,但其目的是只允许玩家开火一次,在玩家再次开火之前,需要有一个键控事件)
根据干净代码的规则,我应该在函数顶部声明变量。。。但这意味着每次我按下一个按钮,它都会被重新声明
上面写着
初始化:当您声明一个变量时,它会自动
初始化,这意味着内存由
JavaScript引擎
所以每次使用let关键字时,我都会创建一个全新的变量
我是否应该在函数的开头写一个条件来检查
firmaused
是否已经声明,如果没有声明它呢?这似乎太过分了。如果您的变量是在全局范围内声明的,那么使用let
或var
实际上并不重要
这些功能相同:
让myVar=123;
函数doStuff(){
console.log(myVar);
}
doStuff()
不,您不应该创建全局变量(无论如何也不要使用let
。是的,如果希望在调用之间共享它,则应该在函数外部声明它 您可以使用闭包实现这一点,使用任何类型的模块模式—从ES6模块到IIFE,再到简单的块范围
// ES6 module
let firePaused = false;
export function actOnKeyPress() {
// use `firePaused`
}
这个问题实际上与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;
}
}
}
})();
看起来您正试图在多个位置维持角色的(英雄)状态。这将变得越来越难以在全局范围内维护,因为每个角色的动作/状态将添加到全局变量中 根据@jeff huijsmans的建议,我认为您应该在
游戏
对象中保持状态
这可以通过以下几种方式进行定义:
game.state.firemaused
-这会将游戏状态锁定为单个角色,但最好包含角色射击的状态game.hero.firemaused
-这允许每个角色保持自己的射击状态。这还有一个额外的好处,就是能够添加更多具有触发状态的角色另一方面,这里的大多数答案似乎都试图解决范围问题。全局定义变量并尝试在函数外部维护状态变得非常难以理解/读取/测试。在这个话题上会有很多意见。幸运的是,对于您的根本问题,您可以通过使用预先存在的状态对象来避免此问题。似乎您有一个全局变量,
game
。那游戏.状态.火力支援呢?这样,如果你把所有与游戏状态相关的变量都放在那里,你甚至可以很容易地保存游戏。有没有可能你可以返回true或false而不是设置一个变量?Sitepoint注释充其量是误导性的,在我看来这完全是错误的。实际上我建议你一直这样做。@Bergi:window
不是有点不对劲吗,使用而不是正确的作用域操作/用法?我不关心变量在窗口中是否可用,问题在于。(现在找到了正确的链接)。对于这个问题,编码约定不是有点超出了“范围”吗?@Cerbrus当那些“模式”(“约定”完全是另一回事)修改范围时不会这样做。吹毛求疵:“所有代码都应该不在全局范围内”<这是一个约定。如何做到这一点,是通过实现某种模式来实现的。@Cerbrus(更挑剔)这是一种“最佳实践”。“约定”是一种普遍接受的做事方式(即命名约定)。有很多方法可以避免全球范围。先生,你只是挑剔了我。
// block scope
var actOnKeyPress;
{
let firePaused = false;
actOnKeyPress = function actOnKeyPress() {
// use `firePaused`
};
}
(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;
}
}
}
})();