ฟังก์ชั่นการโทรและการใช้งานไม่ค่อยใช้ในการดำเนินการ JavaScript อย่างง่าย ในการดำเนินงานขนาดใหญ่อื่น ๆ เช่นการพัฒนาเว็บแอปพลิเคชันฟังก์ชั่นทั้งสองนี้อาจพบได้บ่อยในการพัฒนากรอบ JS นอกจากนี้ยังมีข้อมูลจำนวนมากเกี่ยวกับคำอธิบายของฟังก์ชั่นทั้งสองนี้ แต่ฉันคิดว่าข้อมูลจำนวนมากถูกเขียนหรือคล้ายกันอย่างมากและขาดคำอธิบายแบบลงสู่พื้นดิน ต่อไปฉันพยายามวิเคราะห์และอธิบายฟังก์ชั่นทั้งสองนี้ด้วยแนวคิดที่ชัดเจนและง่ายขึ้น
การคัดลอกรหัสมีดังนี้:
เราสามารถพิจารณาการโทร () และใช้ () เป็นวิธีการของวัตถุบางอย่างและฟังก์ชั่นการโทรทางอ้อมโดยเรียกใช้วิธีการใช้งาน อาร์กิวเมนต์แรกของการโทร () และใช้ () เป็นวัตถุหลักในการเรียกใช้ฟังก์ชัน มันเป็นบริบทการโทรและการอ้างอิงถึงมันได้จากสิ่งนี้ในร่างกายฟังก์ชั่น ในการเรียกใช้ฟังก์ชัน f () บนวิธีการของวัตถุ o คุณสามารถใช้การโทร () และใช้ () เช่นนี้: f.call (o) f.apply (o) [1]
มาวิเคราะห์การโทรก่อน นี่คือคำอธิบายของฟังก์ชั่นการโทรโดย Ecmascript รุ่นที่ 3 [2]: เมื่อวิธีการโทรถูกเรียกโดยวัตถุฟังก์ชั่น (func.call (0)) พารามิเตอร์ที่จำเป็นและพารามิเตอร์ที่ไม่จำเป็นหลายอย่างจะต้องส่งผ่านกระบวนการดำเนินการดังกล่าว:
A หากการเรียกวัตถุการโทรไม่ทำงานข้อผิดพลาดของ TypeError จะถูกโยนลงไป
B ตั้งค่ารายการพารามิเตอร์เป็นว่าง
C หากวิธีที่เรียกว่าผ่านพารามิเตอร์มากกว่าหนึ่งพารามิเตอร์แล้วแทรก arg1, arg2 ... ลงในรายการพารามิเตอร์ในทางกลับกัน
D, ส่งคืนผลลัพธ์ของการโทรแทนที่สิ่งนี้ในฟังก์ชันการโทร (FUNC) ด้วยพารามิเตอร์ที่ผ่าน 1 และปฏิบัติต่อรายการพารามิเตอร์ที่ผ่านเป็นพารามิเตอร์ของฟังก์ชันนี้
ในความเป็นจริงฟังก์ชั่นการโทรคือต้นแบบของวัตถุฟังก์ชัน กล่าวคือฟังก์ชั่นที่เรียกว่าต้องเป็นฟังก์ชั่นด้วย เมื่อโทรหาการโทรนี้เพียงแทนที่สิ่งนี้ในฟังก์ชั่นที่เรียกใช้การโทรด้วยวัตถุที่ส่งผ่าน นี่คือตัวอย่าง:
<script> ฟังก์ชั่น c1 () {this.name = 'Zhang San'; this.age = '24 '; this.sayname = function () {console.log ("นี่คือคลาส C1 ชื่อของฉันคือ:"+this.name+"อายุของฉันคือ"+this.age); }} ฟังก์ชั่น c2 () {this.name = 'li si'; this.age = '25 '; } var c1 = ใหม่ c1 (); var c2 = ใหม่ c2 (); c1.sayname (); c1.sayname.call (c2); </script>ผลการดำเนินการ:
นี่คือหมวดหมู่ C1 ชื่อของฉันคือ: จางซานอายุของฉันอายุ 24 ปี
นี่คือหมวดหมู่ C1 ชื่อของฉันคือ: Li Si My อายุคือ 25
ในรหัสข้างต้นมีการประกาศสองคลาส C1 และ C2 C1 มีสองคุณสมบัติหนึ่งวิธีและ C2 ยังมีคุณสมบัติสองคุณสมบัติเหมือนกับ C1 หลังจากการสร้างอินสแตนซ์, c1.sayname () พิมพ์คุณสมบัติจริง แต่ c1.sayname.call (c2) พิมพ์คุณสมบัติของ C2 ทำไมถึงเป็นเช่นนี้? เนื่องจาก sayname () เป็นฟังก์ชั่นและมีสิ่งนี้อยู่ในร่างกายฟังก์ชันเมื่อมีการเรียกใช้การโทรสิ่งนี้จะถูกแทนที่ด้วย C2 ดังนั้นแอตทริบิวต์ของ C2 จะถูกพิมพ์ในที่สุด
ความแตกต่างระหว่างการสมัครและการโทรอยู่ในการผ่านพารามิเตอร์ทางเลือก พารามิเตอร์ที่เป็นตัวเลือกทั้งหมดของการสมัครจะถูกเก็บไว้ในอาร์เรย์เนื่องจากมีการป้อนพารามิเตอร์หนึ่งตัวในขณะที่การโทรถูกส่งไปยังพารามิเตอร์หลายตัว
ดังนั้นแอปพลิเคชันของฟังก์ชั่นการสมัครและการโทรคืออะไร? สิ่งแรกคือการค้นหาองค์ประกอบที่ใหญ่ที่สุดในอาร์เรย์ตัวเลขบนเครือข่าย คุณสามารถใช้ math.max.apply (null, array) โดยตรง อีกอย่างคือการใช้งานและโทรเพื่อสืบทอดดังนี้:
<script> ฟังก์ชั่นมนุษย์ (ชื่อเพศ) {this.name = name; this.sex = เพศ; this.walk = function () {console.log ('ฉันกำลังเดิน'); }} function child () {human.call (นี่, "Xiao Ming", "Male") this.paly = function () {console.log ('ฉันชอบเล่นมาก'); } this.intruduce = function () {console.log ('สวัสดีทุกคน, i'+this.name); }} var jinp = มนุษย์ใหม่ ('แจ็ค', 'ชาย'); var xiaoping = เด็กใหม่ (); xiaoping.walk (); xiaoping.paly (); xiaoping.intruduce (); </script>ผลการดำเนินการ:
ฉันกำลังเดิน
ฉันชอบเล่นมาก
สวัสดีทุกคนฉันคือ Xiao Ming
ฟังก์ชั่นที่คล้ายกันในการเรียก () และใช้ () คือ bind () ซึ่งเป็นวิธีการใหม่ที่เพิ่มเข้ามาใน eCmascript 5 แต่สามารถจำลองได้ง่ายใน eCmascript 3 ฟังก์ชันการผูกยังเป็นฟังก์ชันวิธีการ prototype ใน JavaScript เนื้อหาหลักของวิธีนี้คือการผูกฟังก์ชันกับวัตถุ เมื่อวิธีการ bind () ถูกผูกไว้กับฟังก์ชัน f () และวัตถุ O จะถูกส่งผ่านเป็นพารามิเตอร์วิธีนี้จะส่งคืนฟังก์ชั่นใหม่และเรียกว่าเป็นวิธีของ O อาร์กิวเมนต์ใด ๆ ที่ส่งผ่านไปยังฟังก์ชั่นใหม่จะถูกส่งผ่านไปยังฟังก์ชั่นดั้งเดิม ดังนี้:
<script> บทนำฟังก์ชั่น (ประเทศ, งานอดิเรก) {return "สวัสดีทุกคนชื่อของฉันคือ"+this.name+", ปีนี้"+this.age+"ปีจาก"+ประเทศ+"เช่น"+Hobby; } var xiaoming = {ชื่อ: "xiao ming", อายุ: 20} var jieshao = แนะนำ. bind (xiaoming); console.log (jieshao ("จีน", "เล่นบอล")); </script>ผลการดำเนินการ:
สวัสดีทุกคนชื่อของฉันคือ Xiao Ming ฉันอายุ 20 ปีจากจีนฉันชอบเล่นบาสเก็ตบอล
ตัวอย่างข้างต้นเทียบเท่ากับ:
<script> บทนำฟังก์ชั่น (ประเทศ, งานอดิเรก) {return "สวัสดีทุกคนชื่อของฉันคือ"+this.name+", ปีนี้"+this.age+"ปีจาก"+ประเทศ+"เช่น"+Hobby; } var xiaoming = {ชื่อ: "xiaoming", อายุ: 20} console.log (แนะนำ. apply (xiaoming, ["จีน", "เล่น"])); // หรือ console.log (แนะนำ. call (Xiaoming, "China", "Play")); </script>ควรสังเกตว่าในโหมดที่เข้มงวดของ ECMASCRIPT 5 อาร์กิวเมนต์แรกของการโทร () และใช้ () จะกลายเป็นค่านี้แม้ว่าการผ่านในอาร์กิวเมนต์จริงจะเป็นค่าดั้งเดิมหรือแม้แต่ค่าว่างหรือไม่ได้กำหนด ในโหมด ECMASCRIPT 3 และ NON-Strict ค่า NULL ที่ผ่านและไม่ได้กำหนดจะถูกแทนที่ด้วยการเผชิญหน้าทั่วโลกในขณะที่ค่าดั้งเดิมอื่น ๆ จะถูกแทนที่ด้วยวัตถุ wrapper ที่เกี่ยวข้อง
การอ้างอิง
[1] คู่มือ JavaScript ที่มีสิทธิ์รุ่นที่ 6 หน้า 189
[2], function.prototype.call (thisarg [, arg1 [, arg2, …])
[3], function.prototype.apply (thisarg, argarray)