JavaScript เวอร์ชันก่อนหน้านี้ไม่อนุญาตการแสดงออกของฟังก์ชั่นที่มีชื่อและเนื่องจากว่าเราไม่สามารถสร้างนิพจน์ฟังก์ชันแบบเรียกซ้ำ:
// 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;
});
ในการหลีกเลี่ยงสิ่งนี้arguments.callee
ถูกเพิ่มเข้ามาเพื่อให้เราทำ:
[1,2,3,4,5].map(function(n) {
return (!(n>1))? 1 : arguments.callee(n-1)*n;
});
อย่างไรก็ตามนี่เป็นวิธีแก้ปัญหาที่ไม่ดีจริง ๆ เช่นนี้ (ร่วมกับข้อโต้แย้งอื่น ๆ ประเด็น callee และปัญหาผู้โทร) ทำให้การเรียกใช้แบบอินไลน์และหางเป็นไปไม่ได้ในกรณีทั่วไป (คุณสามารถบรรลุในกรณีที่เลือกผ่านการติดตาม ฯลฯ ย่อยที่ดีที่สุดเนื่องจากการตรวจสอบที่ไม่จำเป็นอย่างอื่น) ปัญหาที่สำคัญอื่น ๆ คือการเรียกซ้ำจะได้รับthis
ค่าที่แตกต่างตัวอย่างเช่น
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();
อย่างไรก็ตาม EcmaScript 3 สามารถแก้ไขปัญหาเหล่านี้ได้ด้วยการอนุญาตให้นิพจน์ฟังก์ชันที่ระบุชื่อเช่น:
[1,2,3,4,5].map(function factorial(n) {
return (!(n>1))? 1 : factorial(n-1)*n;
});
สิ่งนี้มีประโยชน์มากมาย:
ฟังก์ชั่นนี้สามารถเรียกได้ว่าเหมือนกับฟังก์ชั่นอื่น ๆ จากข้างในโค้ดของคุณ
มันไม่สร้างมลภาวะเนมสเปซ
ค่าของthis
จะไม่เปลี่ยนแปลง
มันมีประสิทธิภาพมากกว่า (การเข้าถึงอ็อบเจกต์อาร์กิวเมนต์มีราคาแพง)
อ๊ะ
เพิ่งตระหนักว่านอกเหนือไปจากทุกสิ่งทุกอย่างคำถามที่เกี่ยวกับหรือมากขึ้นโดยเฉพาะarguments.callee.caller
Function.caller
ณ จุดใดก็ตามคุณสามารถค้นหาผู้เรียกที่ลึกที่สุดของฟังก์ชั่นใด ๆ บนสแต็คและอย่างที่ฉันได้กล่าวไว้ข้างต้นการดูที่ call stack มีเอฟเฟกต์หลักเดียว: มันทำให้การเพิ่มประสิทธิภาพจำนวนมากเป็นไปไม่ได้
เช่น. หากเราไม่สามารถรับประกันได้ว่าฟังก์ชั่นf
จะไม่เรียกฟังก์ชั่นที่ไม่รู้จักนั้นจะไม่สามารถอินไลน์f
ได้ โดยทั่วไปหมายความว่าไซต์การโทรใด ๆ ที่อาจไม่สามารถ inlinable เก็บสะสมยามจำนวนมากได้:
function f(a, b, c, d, e) { return a ? b * c : d * e; }
หากล่าม js ไม่สามารถรับประกันได้ว่าข้อโต้แย้งที่ให้ไว้ทั้งหมดเป็นตัวเลข ณ จุดที่ทำการโทรนั้นจะต้องทำการแทรกการตรวจสอบสำหรับอาร์กิวเมนต์ทั้งหมดก่อนที่โค้ดอินไลน์หรือไม่สามารถอินไลน์ฟังก์ชันได้
ตอนนี้ในกรณีนี้ล่ามอัจฉริยะควรสามารถจัดเรียงเช็คใหม่ให้เหมาะสมที่สุดและไม่ตรวจสอบค่าใด ๆ ที่ไม่ควรใช้ อย่างไรก็ตามในหลายกรณีที่เป็นไปไม่ได้และดังนั้นจึงเป็นไปไม่ได้ที่จะอินไลน์