f=_=>do{try{-~f()}catch(e){}}
- 2 bytes salvos graças a Neil.
Experimente aqui ou use o Snippet abaixo para testá-lo em evalvez de do.
console.log((f=_=>eval(`try{-~f()}catch(e){}`))())
JaptPorta , 24 bytes
Não vale a pena postar isso como uma solução separada, pois é essencialmente idêntico.
Ox`try\{-~rp()}¯t®(e)\{}
Teste-o
Explicação
O próprio JavaScript não possui um limite de recursão propriamente dito, mas o limite é imposto pelo intérprete (ou seja, pelo navegador) - é bom definirmos idiomas pelo intérprete deles 'por aqui! Entre outros fatores, o limite pode variar de acordo com o navegador e a memória disponível, impactada pelas operações que estão sendo executadas. O Snippet a seguir ilustra esse último ponto, usando as 5 versões diferentes desta solução pelas quais passei. Como você pode ver nos dois últimos testes, no Chrome, pelo menos, até a ordem das operações pode fazer a diferença.
console.log((f=(i=0)=>eval(`try{f(i+1)}catch(e){i}`))())
console.log((f=i=>eval(`try{f(-~i)}catch(e){i}`))())
console.log((f=(i=0)=>eval(`try{f(++i)}catch(e){i}`))())
console.log((f=_=>eval(`try{-~f()}catch(e){}`))())
console.log((f=_=>eval(`try{f()+1}catch(e){0}`))())
console.log((f=_=>eval(`try{1+f()}catch(e){0}`))())
Sendo assim, não temos a conveniência de uma constante ou método para trabalhar. Em vez disso, vamos criar uma função que se autodenomina continuamente antes, eventualmente, de exagerar. Na sua forma mais simples, é:
f=_=>f()
Mas isso não nos serve muito para esse desafio, pois gera apenas um erro de estouro, sem indicação de quantas vezes se fchamou. Podemos evitar o erro trying ao chamadof continuamente e catching quando ele falhar:
f=_=>{try{f()}catch(e){}}
Sem erro, mas ainda sem valor de retorno de quantas vezes a função conseguiu se chamar antes de falhar, porque na catchverdade não está fazendo nada. Vamos tentar avaliar a try / catchdeclaração:
f=_=>eval(`try{f()}catch(e){}`)
Agora temos um valor a ser devolvido (e, porque este é o golfe código, salvo se estabeleceu alguns bytes sobre o uso de um real return). O valor retornado, no entanto, é undefinednovamente porque catchnão está fazendo nada. Felizmente para nós, -~undefined==1e -~n==n+1assim, pressionando um -~na frente da chamada f, basicamente recebemos -~-~ ... -~-~undefineduma outra -~anexada a cada chamada, fornecendo o número de vezes que ela ffoi chamada.
f=_=>eval(`try{-~f()}catch(e){}`)