ครั้งแรกที่ฉันแปลบทความทางเทคนิคฉันหัวเราะเยาะคุณ!
ข้อความต้นฉบับแปล:
function.apply และ function.call ใน JavaScript
ย่อหน้าแรกถูกละเว้น
แต่ละฟังก์ชั่น JavaScript มีวิธีการที่แนบมามากมายรวมถึง ToString (), call () และ appl () ดูเหมือนว่าคุณจะพบว่ามันแปลกที่ฟังก์ชั่นอาจมีวิธีการของตัวเอง แต่โปรดจำไว้ว่าทุกฟังก์ชั่นใน JavaScript เป็นวัตถุ ดูบทความนี้และตรวจสอบคุณสมบัติ JavaScript (ทบทวน) คุณอาจต้องการทราบความแตกต่างระหว่างฟังก์ชั่นและวิธีการใน JavaScript ฉันคิดว่าคำอธิบายของ "ฟังก์ชั่น" และ "วิธีการ" เป็นเพียงการประชุมที่เป็นนิสัยของ JavaScript ฟังก์ชั่นขึ้นอยู่กับตัวเอง (ตัวอย่างเช่น: Alert ()) และวิธีการเป็นคุณลักษณะของวัตถุภายในฟังก์ชั่น (พจนานุกรม) และเราเรียกวิธีการผ่านวัตถุ แต่ละวัตถุ JavaScript มีวิธี TOSTRING () ต่อไปนี้เป็นตัวอย่างของรหัส ในวัตถุฟังก์ชันเราสามารถใช้วิธี ToString ()
function foo () {Alert ('x');} Alert (foo.toString ());เนื่องจากฟังก์ชั่นเป็นวัตถุพวกเขาจึงมีคุณสมบัติและวิธีการของตนเอง เราสามารถคิดว่าพวกเขาเป็นข้อมูล ในบทความนี้เรามุ่งเน้นไปที่วิธีการของสองฟังก์ชั่นใช้ () และการโทร () เท่านั้น
เริ่มต้นด้วยรหัสต่อไปนี้:
var x = 10; ฟังก์ชั่น f () {การแจ้งเตือน (this.x);} f ();เรากำหนดฟังก์ชั่นทั่วโลก f () f () เข้าถึงตัวแปร x ผ่านคำหลักนี้ แต่ควรสังเกตว่าเราไม่สามารถเรียกฟังก์ชั่นนี้ผ่านอินสแตนซ์ของวัตถุ จุดนี้มีวัตถุอะไร? สิ่งนี้จะชี้ไปที่วัตถุระดับโลกนี้ ตัวแปร X ของเราถูกกำหนดไว้ในวัตถุระดับโลกนี้ รหัสข้างต้นสามารถทำงานได้ตามปกติ ผลลัพธ์ที่รันจะแสดงกล่องโต้ตอบและ 10 จะปรากฏขึ้นในกล่องโต้ตอบ
เราสามารถโทร () และสมัคร () ผ่านสิ่งนี้ ดังตัวอย่างต่อไปนี้แสดงวิธีใช้การโทร ():
var x = 10; var o = {x: 15}; ฟังก์ชั่น f () {การแจ้งเตือน (this.x);} f (); f.call (o);ก่อนอื่นการเรียก f () จะแสดงกล่องโต้ตอบ 10 เนื่องจากจุดนี้ไปยังวัตถุทั่วโลกในเวลานี้ จากนั้นเราเรียกวิธีการโทร () ของฟังก์ชัน F พารามิเตอร์ที่ส่งผ่านคือ O และผลลัพธ์การเรียกใช้แสดงค่าของแอตทริบิวต์ x ใน O 15 วิธีการโทร () จะใช้พารามิเตอร์แรกเป็นตัวชี้นี้ไปยังฟังก์ชัน F นั่นคือเราจะบอกรันไทม์ที่คัดค้านสิ่งนี้ในฟังก์ชัน F ชี้ไปที่
การกระโดดนี้ฟังดูตลกเล็กน้อยและแม้แต่ความผิดปกติสำหรับโปรแกรมโปรแกรมเมอร์ C ++, Java และ C# เหล่านี้เป็นส่วนที่น่าสนใจของ ecmascript
นอกจากนี้คุณยังสามารถส่งผ่านพารามิเตอร์ไปยังฟังก์ชันผ่านการโทร ():
var x = 10; var o = {x: 15}; ฟังก์ชั่น f () {การแจ้งเตือน (this.x);} f (); f.call (o);ใช้ () และการโทร () คล้ายกันยกเว้นว่าใช้ () ต้องการให้พารามิเตอร์ที่สองต้องเป็นอาร์เรย์ อาร์เรย์นี้จะถูกส่งผ่านเป็นอาร์กิวเมนต์ไปยังฟังก์ชันเป้าหมาย
var x = 10; var o = {x: 15}; ฟังก์ชั่น f (ข้อความ) {แจ้งเตือน (ข้อความ); การแจ้งเตือน (this.x);} f ('เรียกใช้ f'); f.apply (o, ['เรียกใช้ f ผ่านการใช้']);วิธีการใช้งาน () มีประโยชน์เพราะเราสามารถสร้างฟังก์ชั่นโดยไม่ต้องสนใจเกี่ยวกับพารามิเตอร์ของวิธีเป้าหมาย ฟังก์ชั่นนี้สามารถผ่านพารามิเตอร์เพิ่มเติมไปยังวิธีการผ่านพารามิเตอร์อาร์เรย์ที่สองของ Apply ()
var o = {x: 15}; ฟังก์ชั่น f1 (ข้อความ 1) {แจ้งเตือน (ข้อความ 1 + this.x);} ฟังก์ชั่น f2 (ข้อความ 1, ข้อความ 2) {แจ้งเตือน (ข้อความ 1 + (this.x * this.x) + message2); ['ค่าของ x squared =', 'ว้าว!'];มีบางอย่างผิดปกติกับไวยากรณ์นี้ ในการเรียกใช้วิธีการใช้ () เราบังคับให้ฟังก์ชันวัตถุประสงค์เพื่อใช้พารามิเตอร์ในอาร์เรย์ โชคดีที่มีวิธีทำให้ไวยากรณ์นี้ง่ายขึ้น ก่อนหน้านี้เราต้องแนะนำหนึ่ง: ตัวระบุพารามิเตอร์
ใน JavaScript แต่ละฟังก์ชั่นมีรายการพารามิเตอร์ความยาวตัวแปร ซึ่งหมายความว่าแม้ว่าฟังก์ชั่นจะมีพารามิเตอร์เดียวเท่านั้นเราสามารถส่งพารามิเตอร์ 5 พารามิเตอร์ได้ รหัสต่อไปนี้จะไม่มีข้อผิดพลาดใด ๆ และผลลัพธ์จะแสดง "H"
ฟังก์ชั่น f (ข้อความ) {แจ้งเตือน (ข้อความ);} f ('h', 'e', 'l', 'l', 'o');ใน f () ถ้าเราไม่ต้องการยอมรับพารามิเตอร์อื่น ๆ เราสามารถใช้อาร์กิวเมนต์คำหลัก อาร์กิวเมนต์แสดงถึงวัตถุอาร์กิวเมนต์ซึ่งมีแอตทริบิวต์ที่แสดงถึงความยาวคล้ายกับอาร์เรย์
ฟังก์ชั่น f (ข้อความ) {// ค่าของข้อความเหมือนกับอาร์กิวเมนต์ [0] สำหรับ (var i = 1; i <arguments.length; i ++) {message+= อาร์กิวเมนต์ [i]; } Alert (ข้อความ);} // ผลลัพธ์แสดง "hello" f ('h', 'e', 'l', 'l', 'o');คุณควรรู้ว่าการพูดอย่างเคร่งครัดข้อโต้แย้งไม่ใช่อาร์เรย์ อาร์กิวเมนต์มีแอตทริบิวต์ความยาว แต่ไม่มีวิธีการแยกกดและป๊อป ในฟังก์ชั่น g () ก่อนหน้านี้เราสามารถคัดลอกพารามิเตอร์ที่ต้องการจากอาร์กิวเมนต์รูปแบบอาร์เรย์จากนั้นผ่านอาร์เรย์นี้เพื่อใช้ ()
var o = {x: 15}; ฟังก์ชั่น f (ข้อความ 1, message2) {แจ้งเตือน (ข้อความ 1 + (this.x * this.x) + message2);} ฟังก์ชั่น g (วัตถุ, func) {// อาร์กิวเมนต์ [0] = วัตถุ // อาร์กิวเมนต์ [1] = func var args = []; สำหรับ (var i = 2; i <arguments.length; i ++) {args.push (อาร์กิวเมนต์ [i]); } func.apply (วัตถุ, args);} g (o, f, 'ค่าของ x squared =', '. ว้าว!');เมื่อเราเรียก G () เราสามารถส่งอาร์กิวเมนต์เพิ่มเติมเป็นพารามิเตอร์แทนการบรรจุอาร์กิวเมนต์ลงในอาร์เรย์