JavaScript'in önceki sürümleri adlandırılmış işlev ifadelerine izin vermedi ve bu nedenle yinelemeli işlev ifadesi yapamadık:
// This snippet will work:
function factorial(n) {
return (!(n>1))? 1 : factorial(n-1)*n;
}
[1,2,3,4,5].map(factorial);
// But this snippet will not:
[1,2,3,4,5].map(function(n) {
return (!(n>1))? 1 : /* what goes here? */ (n-1)*n;
});
Bunu aşmak için ekleyebildik arguments.callee
:
[1,2,3,4,5].map(function(n) {
return (!(n>1))? 1 : arguments.callee(n-1)*n;
});
Bununla birlikte, bu gerçekten kötü bir çözümdü (bu, diğer argümanlar, callee ve arayan sorunları ile birlikte) genel durumda satır içi ve kuyruk yinelemeyi imkansız hale getiriyor (izleme vb. aksi takdirde gerekli olmayan kontroller nedeniyle alt optimaldir). Diğer önemli sorun, özyinelemeli çağrının farklı bir this
değer almasıdır, örneğin:
var global = this;
var sillyFunction = function (recursed) {
if (!recursed)
return arguments.callee(true);
if (this !== global)
alert("This is: " + this);
else
alert("This is the global");
}
sillyFunction();
Her neyse, EcmaScript 3, adlandırılmış işlev ifadelerine izin vererek bu sorunları çözdü, örneğin:
[1,2,3,4,5].map(function factorial(n) {
return (!(n>1))? 1 : factorial(n-1)*n;
});
Bunun birçok faydası vardır:
Bu fonksiyon, kodunuzun içinden herhangi biri gibi çağrılabilir.
Ad alanını kirletmez.
Değeri this
değişmez.
Daha performanslıdır ( arguments nesnesine erişmek pahalıdır).
, Whoops
Sorunun diğer her şeye ek olarak arguments.callee.caller
veya daha spesifik olarak olduğunu fark ettim Function.caller
.
Herhangi bir zamanda, yığındaki herhangi bir işlevin en derin arayanını bulabilirsiniz ve yukarıda söylediğim gibi, çağrı yığınına bakmanın tek bir büyük etkisi vardır: Çok sayıda optimizasyonu imkansız veya çok daha zor hale getirir.
Örneğin. bir işlevin f
bilinmeyen bir işlevi çağırmayacağını garanti edemezsek, satır içi yapmak mümkün değildir f
. Temel olarak, önemsiz derecede inline edilmiş olabilecek herhangi bir çağrı sitesinin çok sayıda koruma biriktirdiği anlamına gelir:
function f(a, b, c, d, e) { return a ? b * c : d * e; }
Js yorumlayıcısı, sağlanan tüm bağımsız değişkenlerin çağrının yapıldığı noktadaki sayılar olduğunu garanti edemezse, satır içi koddan önce tüm bağımsız değişkenler için denetimler eklemesi gerekir veya işlevi satır içinde yapamaz.
Şimdi bu özel durumda akıllı bir tercüman kontrolleri daha uygun olacak şekilde yeniden düzenleyebilmeli ve kullanılmayacak herhangi bir değeri kontrol etmemelidir. Bununla birlikte, birçok durumda bu mümkün değildir ve bu nedenle satır içi yapmak imkansız hale gelir.