JavaScript: pile d'appels et la magie de sa taille

Bonjour, Khabrovites!





La plupart des développeurs qui ont utilisé la récursivité pour résoudre leurs problèmes ont vu cette erreur:





 RangeError: Maximum call stack size exceeded. 
      
      



Mais tous les développeurs n'ont pas réfléchi à ce que signifie «taille de pile d'appel» et quelle est cette taille? Et comment le mesurer?





Je pense que ceux qui travaillent avec des langages qui fonctionnent directement avec la mémoire peuvent facilement répondre à cette question, mais un développeur front-end typique se pose très probablement de telles questions pour la première fois. Eh bien, essayons de le comprendre!





Beaucoup de gens pensent que le navigateur nous limite précisément dans le nombre d'appels, mais ce n'est pas le cas. Dans cet article, je vais vous montrer avec des exemples simples comment cela fonctionne réellement.





De quoi parlez-vous, auteur?

Pour l'article, il est important de comprendre des concepts tels que la pile d'exécution, le contexte d'exécution. Si vous ne savez pas ce que c'est, alors je vous conseille de lire à ce sujet. Cette ressource a déjà eu suffisamment de bons articles sur ce sujet. Exemple -  https://habr.com/ru/company/ruvds/blog/422089/





Quand cette erreur se produit-elle?

Prenons un exemple simple - une fonction qui s'appelle récursivement.





const func = () => {
    func();
}
      
      



Si nous essayons d'appeler une telle fonction, nous verrons l'erreur dans la console / le terminal, que j'ai mentionnée ci-dessus.





Mais que se passe-t-il si vous regardez combien de fois la fonction a été exécutée avant que l'erreur ne se produise?





Chrome DevTools 2021. . .





:





let i = 0;

const func = () => {
  i++;

  func();
};

try {
  func();
} catch (e) {
  //          
  console.log(i);
}
      
      



13914. , , , 14 .





, . , :





let i = 0;

const func = () => {
  let someVariable = i + 1;
  i++;

  func();
};

try {
  func();
} catch (e) {
  console.log(i);
}
      
      



, , someVariable



  . , , . 12523 . , . , , , .





? ? , , ?!





- . . , , - . -, , , ? , ? : 





let i = 0;

const func = () => {
  let a = i + 1;
  let b = a + 1;
  let c = b + 1;
  let d = c + 1;
  let e = d + 1;
  i++;

  func();
};

try {
  func();
} catch (e) {
  console.log(i);
}
      
      



, . , - 8945. , . , . , .





Execution Stack (Call Stack) - . . , . , , . . , , .





. -   . - , . Call Stack (Execution Stack), , Execution Context - ( this). , , "" , , . Execution Context, , . "" , .





. , ? , , Chrome?





-

, , (, ). Execution Stack, . N, K. X.





- , ( ) :





FunctionSize = N + K * SizeOfVar

SizeOfVar - , .





, , , :





X = (N + 0 * SizeOfVar) * 13914 = N * 13914

, , , .





X = (N + 5 * SizeOfVar) * 8945

- . , .





N * 13914 = (N + 5 * SizeOfVar) * 8945

. - N SizeOfVar. N - , SizeOfVar? , , , "number", , , .





- " JavaScript 64- . 8 , 64/8 = 8 ." - . 8 . , N.





N * 13914 = (N + 5 * 8) * 8945

:





N * 13914 = N * 8945 + 40 * 8945

N, : N 72. 72 .





, N = 72 , , Chrome ... 1002128 . . , .





- , , ? , , 7 'number'. 





: , (72 + 7 * 8) , 128. 1002128 128 ... 7829! , 7829 !  ...





. 3. , . , , , - . - .



, , ExecutionStack Chrome 72 , - .



!





. .  . 45606 . 39905 . NodeJS Chrome . JavaScript. 





?

, Object? 





let i = 0;

const func = () => {
  const a = {
    key: i + 1,
  };
  i++;

  func();
};

try {
  func();
} catch (e) {
  console.log(i);
}
      
      



. 12516. , . JS' - . , .





? ? *?

, . , . , , . , .





:

  • .





  • .





  • "" , .





  • .





: "number" , , ?








All Articles