Почему работает функция JavaScript

236
11 сентября 2021, 13:40

Почему этот код работает?
Вот какая я думаю, почему он работает:
1) Переменные все сохраняются и срабатывает вызов функции gameEngineStart(gameLoopRight)
2) Выполняются тело функции gameEngineStart ->
gameEngine = телу функции gameLoopRight, потом срабытывает вызов функции gameEngineStep()
3) Выполняется функция gameEngineStep ->
вызывается reqAnimFrame(gameEngineStep), reqAnimFrame становится ссылкой на функцию requestAnimationFrame, если всё хорошо, иначе возвращается название функции для нужного браузера, а потом уже обычный setTimeout
reqAnimFrame вызывается с аргументом gameEngineStep, который должен был вызвать саму себя(по логике) и так бесконечно. Но дальше происходит срабатывание gameEngine()
Дальше всё понятно как работает, но вот этот момент непонятен, почему функция не вызывает саму себя бесконечно, а может выполнить вызов gameEngine()?

var gameEngine; 
var canvas = document.getElementById('canvas'); 
var context = canvas.getContext('2d'); 
var x = 10, y = 10; 
 
function drawRect() { 
	context.fillStyle = 'black'; 
	context.clearRect(0, 0, 300, 300); 
	context.fillRect(x, y, 50, 50); 
} 
 
var reqAnimFrame = (function() { 
	return requestAnimationFrame       || 
	       mozRequestAnimationFrame    || 
	       webkitRequestAnimationFrame || 
	       oRequestAnimationFrame      || 
	       msRequestAnimationFrame     || 
	function (callback) { 
    	setTimeout(callback, 1000 / 60); 
    } 
})(); 
 
function gameEngineStart(callback) { 
	gameEngine = callback; 
	gameEngineStep(); 
} 
 
function gameEngineStep() { 
	reqAnimFrame(gameEngineStep); 
	gameEngine(); 
} 
 
function setGameEngine(callback) { 
	gameEngine = callback; 
} 
 
function gameLoopRight() { 
	drawRect(); 
	x += 2; 
	if (x >= 240) { 
		setGameEngine(gameLoopLeft); 
	} 
} 
 
function gameLoopLeft() { 
	drawRect(); 
	x -= 2; 
	if (x < 20) { 
		setGameEngine(gameLoopRight); 
	} 
} 
 
gameEngineStart(gameLoopRight);
#canvas { 
	border: 1px solid black; 
}
<canvas id="canvas" width="300px" height="70px"></canvas>

Answer 1

Я точно не понял полностью как работает requestAnimationFrame, но при выводе в консоль сообщения из функции gameEngineStep, оно выводилось 60 раз в секунду. Я пытался тоже самое проделать(вызвать саму себя функцией, без таймеров), но без requestAnimationFrame, в итоге всё глючило и браузер не отвечал. requestAnimationFrame работает так, что она не нагрузит процессор, если вызывать функцию рекурсивно, она будет вызываться только 60 раз в секудну(обычно, зависит от монитора).
Мне не нравится, что requestAnimationFrame (я так думаю, возможно это неправильно) срабатывает больше раз, чем необходимо для отрисовки, т.е. некоторые вызовы функции происходят просто так. В будущем планирую разобраться, как это работает, когда пойму

Answer 2

примерно ваша цитата: а потом уже обычный таймаут с вечным циклом.

как работает таймаут? вызывается, запоминает что ему ныжно выпольнить что-то там черзе какое то время. и все. вышел из функции. и пошел работать код дальше:

function gameEngineStep() {
    reqAnimFrame(gameEngineStep);
    gameEngine();
}

а дальше - gameEngine() Вот, а когда пройдет положенное время внезапно в параллельном процессе исполнится то что запомнил сетТаймаут. В параллельном! И помните, каждый вызов сетТаймаут дает именно параллельный процесс.

READ ALSO
Навигация по массиву клавишами

Навигация по массиву клавишами

Есть такой сильно упрощенный код

107
Алгоритм простых чисел в JS

Алгоритм простых чисел в JS

Понимаю как нелепо может выглядеть этот вопрос,и как криво я описал проблему,но я новичок в этом деле,так что сорре

182
Как исключить многократную загрузку Javascript?

Как исключить многократную загрузку Javascript?

В расширении Google Chrome, установлено событие, которое отслеживает загрузку определенной страницы сайта exemplecom:

87