JavaScript: pilha de chamadas e a magia de seu tamanho

Olá, Khabrovites!





A maioria dos desenvolvedores que usou a recursão para resolver seus problemas viu este erro:





 RangeError: Maximum call stack size exceeded. 
      
      



Mas nem todo desenvolvedor pensou sobre o que significa "tamanho da pilha de chamadas" e qual é esse tamanho? E como medi-lo?





Eu acho que aqueles que trabalham com linguagens que trabalham diretamente com a memória podem facilmente responder a essa pergunta, mas um desenvolvedor front-end típico está provavelmente se perguntando essas questões pela primeira vez. Bem, vamos tentar descobrir!





Muitas pessoas acreditam que o navegador nos limita justamente no número de chamadas, mas não é o caso. Neste artigo, mostrarei a você exemplos simples de como ele realmente funciona.





Do que você está falando, autor?

Para o artigo, é importante entender conceitos como Execution Stack, Execution Context. Se você não sabe o que é, aconselho que leia a respeito. Este recurso já tem artigos bons o suficiente sobre este tópico Exemplo -  https://habr.com/ru/company/ruvds/blog/422089/





Quando esse erro ocorre?

Vamos dar um exemplo simples - uma função que se chama recursivamente.





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



Se tentarmos chamar essa função, veremos o erro no console / terminal, que mencionei acima.





Mas e se você olhar quantas vezes a função foi executada antes de ocorrer o erro?





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