JS global "let" variable not updating in function?
As everybody commented out it seems to be a Chrome
issue.
I've tried to reproduce the same issue on Chrome
version 45.0.2454.85 m (64-bit)
and 44.0.2403.107 m (32-bit)
(enabling strict mode of course) but I've not succeded. But on version 54.0.2840.99 m (64-bit)
it is there.
And I noticed that changing requestAnimationFrame
to something like setInterval
also makes the problem totally go away.
So, I assume that this strange behaviour has something to do with Chrome's
requestAnimationFrame
on newer versions, and maybe block scoping nature of let
, and function hoisting.
I can't say from which version of Chrome
we can see this kind of "bug", but I can assume that it can be the version 52
, because in this version many changes occured, like new method of Garbage collection
, native support for es6
and es7
etc. For more information you can watch this video from I/O 2016
.
Maybe, new Garbage collection
method is causing this issue, because as they told in the above mentioned video it is connected with browser frames, something like v8
does GC when the browser is idle, in order not to touch the drawing of frames etc. And as we know that requestAnimationFrame
is a method which calls a callback
on the next frame drawing, maybe in this process these weird thing's happening. But this is just an assumption and I've no competence to say something serious about this:)
I'm on Chrome 54.0.2840.98 on Mac and it happens too. I think it's a scoping issue, because if I wrap the declaration following the let
statement into a {…}
block, then the snippet works fine and both values change immediately after key press.
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>