gpt4 book ai didi

javascript - JS 全局 "let"变量未在函数中更新?

转载 作者:行者123 更新时间:2023-12-03 13:37:42 24 4
gpt4 key购买 nike

编辑:我已将此报告为 Chromium 错误:https://bugs.chromium.org/p/chromium/issues/detail?id=668257

我正在用 JS 创建一个带有可以射击的敌人的小 Canvas 游戏。为了测试,我创建了一个标志,全局声明为 let fancy = true; ,以确定是否使用“花式”定位算法。我这样做是为了按 P 将切换此标志。我的主要功能,frame ,调用另一个函数,autoShoot ,每秒五次。 autoShoot使用 fancy旗帜。

今天,奇怪的事情开始发生了;我不记得是什么变化引入了它。有时,当我按 P 时,autoShoot行为类似于 fancy没有切换。我做了一些调试,发现新的切换值反射(reflect)在 frame 中。 , 但在 autoShoot ,值不会更新。它间歇性地发生,有时 autoShoot 中的值会自行修复(我没有做任何事情)。

我已将代码简化为以下代码,这对我来说仍然存在问题。尝试按 P 几次。对我来说,这两个值在按 P 一次或两次后“不同步”并显示不同:

Screenshot after pressing P on my computer

(我在 Windows 10 上运行 Chrome“版本 54.0.2840.99 m”。)

const canvas = document.getElementById("c");
const width = 0;
const height = 0;
const ctx = canvas.getContext("2d");
const ratio =1;// (window.devicePixelyRatio||1)/(ctxFOOOOOOOOFOOOOOOOOOFOOOOO||1);
canvas.width = width*ratio;
canvas.height = height*ratio;
canvas.style.width = width+"px";
canvas.style.height = height+"px";
ctx.scale(ratio, ratio);

function testSet(id, val) {
console.log(id+": "+val);
document.getElementById(id).innerText = val;
}


let fancy = true;
document.body.addEventListener("keydown", function(e) {
if (e.keyCode == 80) {
fancy = !fancy;
console.log("Set fancy to: "+fancy);
}
});

let bullets = Array(2000);
let lastTime = 0, shotTimer = 0;
function frame(time) {
const dt = (time - lastTime)/1000;
lastTime = time;

if ((shotTimer -= dt) <= 0) {
testSet("frame", fancy);
autoShoot();
shotTimer = 0.2;
}
for (let b of bullets) {}

requestAnimationFrame(frame);
}
function autoShoot() {
testSet("autoShoot", fancy);
}

requestAnimationFrame(frame);
<code>
fancy (frame) = <span id="frame"></span><br>
fancy (autoShoot) = <span id="autoShoot"></span>
</code>
<canvas id="c"></canvas>


玩玩,这里有一些观察:
  • 删除以下任何一项都会导致问题消失:
  • 顶部代码中处理 Canvas 的任何行,甚至是 只是 const ratio 之后的评论
  • 空的 for...of 循环:for (let b of bullets) {}
  • 变化let fancy =var fancy =或只是 fancy =
  • 将整个事物置于全局范围之外(通过使用 IIFE、onload 处理程序或 block 范围)
  • 增加 bullets 的大小数组增加了问题发生的频率。我认为这是因为它使 frame执行时间更长;原来,bullets.length只有 20 个,但每次循环迭代都会做一些事情来更新项目符号等。

  • 这是否发生在您的计算机上?这有什么合乎逻辑的解释吗?我试过重启浏览器,没有任何变化。

    最佳答案

    正如大家评论的那样,它似乎是 Chrome问题。

    我试图在 Chrome 上重现相同的问题版本 45.0.2454.85 m (64-bit)44.0.2403.107 m (32-bit) (当然启用严格模式)但我没有成功。但是在版本 54.0.2840.99 m (64-bit)它在那里。

    我注意到更改 requestAnimationFrame类似于 setInterval也使问题完全消失。

    所以,我认为这种奇怪的行为与 Chrome's 有关。 requestAnimationFrame在较新的版本上,可能会阻止 let 的范围界定性质,以及功能提升。

    我不能说是哪个版本的Chrome我们可以看到这种“错误”,但我可以假设它可能是版本 52 ,因为在这个版本中发生了很多变化,比如 Garbage collection 的新方法, 原生支持 es6es7等更多信息您可以观看this video from I/O 2016 .

    也许,新的 Garbage collection方法导致此问题,因为正如他们在上述视频中所说,它与浏览器框架连接,例如 v8在浏览器空闲时进行 GC,以便不触摸帧的绘制等。正如我们所知,requestAnimationFrame是一个调用 callback 的方法在下一帧绘图中,也许在这个过程中这些奇怪的事情正在发生。但这只是一个假设,我没有能力对此说些严肃的话:)

    关于javascript - JS 全局 "let"变量未在函数中更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40732294/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com