สมัครโทร
ใน JavaScript การโทรและการใช้งานมีอยู่เพื่อเปลี่ยนบริบท (บริบท) ของฟังก์ชันเมื่อทำงาน กล่าวอีกนัยหนึ่งคือการเปลี่ยนทิศทางของสิ่งนี้ภายในร่างกายฟังก์ชั่น
คุณลักษณะที่สำคัญของ JavaScript คือฟังก์ชั่นมีแนวคิดของ "บริบทคำจำกัดความ" และ "บริบทรันไทม์" และ "บริบทสามารถเปลี่ยนแปลงได้"
ก่อนอื่นรับเกาลัด:
ฟังก์ชั่นผลไม้ () {} fruits.prototype = {color: "สีแดง", พูด: function () {console.log ("สีของฉันคือ" + this.color);}} var apple = ผลไม้ใหม่; Apple.say (); // สีของฉันเป็นสีแดงแต่ถ้าเรามีวัตถุกล้วย = {สี: "สีเหลือง"} และเราไม่ต้องการกำหนดวิธีการพูดใหม่เราสามารถใช้วิธีการพูดของแอปเปิ้ลโดยโทรหรือสมัคร:
Banana = {color: "Yellow"} Apple.say.call (Banana); // สีของฉันคือ Yellowapple.say.apply (Banana); // สีของฉันเป็นสีเหลืองดังนั้นจะเห็นได้ว่าการโทรและการใช้ดูเหมือนจะเปลี่ยนสิ่งนี้แบบไดนามิก เมื่อวัตถุไม่มีวิธีการบางอย่าง (กล้วยไม่ได้พูดวิธีการในเกาลัดนี้) แต่สิ่งอื่นคือ (Apple มีวิธีการพูดในเกาลัดนี้) เราสามารถใช้การโทรหรือใช้เพื่อใช้งานกับวิธีการอื่น ๆ
ความแตกต่างระหว่างการสมัครและการโทร
สำหรับทั้งการใช้และการโทรฟังก์ชั่นจะเหมือนกันทุกประการ แต่วิธีการยอมรับพารามิเตอร์นั้นแตกต่างกัน ตัวอย่างเช่นมีฟังก์ชั่นที่กำหนดดังนี้:
var func = function (arg1, arg2) {};คุณสามารถเรียกมันด้วยวิธีต่อไปนี้:
func.call (this, arg1, arg2); func.apply (this, [arg1, arg2])
ในกรณีที่นี่เป็นบริบทที่คุณต้องการระบุอาจเป็นวัตถุ JavaScript ใด ๆ (ทุกอย่างใน JavaScript เป็นวัตถุ) การโทรต้องผ่านพารามิเตอร์ตามลำดับและใช้หมายถึงการใส่พารามิเตอร์ในอาร์เรย์
ใน JavaScript จำนวนพารามิเตอร์ของฟังก์ชันไม่ได้รับการแก้ไขดังนั้นหากคุณต้องการพูดเงื่อนไขที่เกี่ยวข้องให้ใช้การโทรเมื่อพารามิเตอร์ของคุณเป็นที่รู้จักอย่างชัดเจน
เมื่อคุณไม่แน่ใจให้ใช้ใช้แล้วกดพารามิเตอร์ลงในอาร์เรย์และส่งผ่านเมื่อจำนวนพารามิเตอร์ไม่แน่นอนพารามิเตอร์ทั้งหมดสามารถเคลื่อนที่ผ่านอาร์เรย์เทียมของอาร์เรย์ภายในฟังก์ชั่น
เพื่อรวมและหน่วยความจำให้ลึกซึ้งยิ่งขึ้นต่อไปนี้เป็นการใช้งานทั่วไปบางอย่าง:
ผนวกเข้ากับอาร์เรย์
var array1 = [12, "foo", {name "joe"}, -2458]; var array2 = ["doe", 555, 100]; array.prototype.push.apply (array1, array2); / * array1 ค่าคือ [12, "foo", {name "joe"}, -2458, "doe", 555, 100] *//รับค่าสูงสุดและต่ำสุดในอาร์เรย์
ตัวเลข var = [5, 458, 120, -215]; var maxinnumbers = math.max.apply (คณิตศาสตร์, ตัวเลข), // 458maxinnumbers = math.max.call (คณิตศาสตร์, 5, 458, 120, -215); // 458
หมายเลขเองไม่มีวิธีสูงสุด แต่คณิตศาสตร์มีดังนั้นเราจึงสามารถใช้วิธีการโทรหรือสมัคร
ตรวจสอบว่าเป็นอาร์เรย์ (โดยมีเงื่อนไขว่าวิธีการ ToString () ยังไม่ได้รับการเขียนใหม่)
FunctionIsarray (obj) {return object.prototype.toString.call (obj) === '[อาร์เรย์วัตถุ]';}อาร์เรย์คลาส (pseudo) โดยใช้วิธีอาร์เรย์
var domnodes = array.prototype.slice.call (document.getElementsByTagname ("*"));มีโครงสร้างวัตถุที่เรียกว่า Pseudo-Array ใน JavaScript สิ่งที่พิเศษกว่าคือวัตถุอาร์กิวเมนต์และยังมีผู้ที่เรียก GetElementsByTagname, document.childnodes ฯลฯ ซึ่งส่งคืนวัตถุที่มี nodelist ทั้งหมดเป็นของอาร์เรย์หลอก คุณไม่สามารถใช้ push, pop และวิธีอื่น ๆ ภายใต้อาร์เรย์
แต่เราสามารถแปลง array.prototype.slice.call เป็นอาร์เรย์จริงด้วยวัตถุที่มีแอตทริบิวต์ความยาวเพื่อให้ domnodes สามารถใช้วิธีทั้งหมดภายใต้อาร์เรย์
เข้าใจอย่างลึกซึ้งและใช้งานและโทร
มาขอยืมคำถามสัมภาษณ์เพื่อทำความเข้าใจกับการสมัครและโทรอย่างลึกซึ้งยิ่งขึ้น
กำหนดวิธีการบันทึกเพื่อให้สามารถพร็อกซีเมธอด console.log ทางออกทั่วไปคือ:
ฟังก์ชั่นบันทึก (msg) {console.log (msg);} log (1); // 1log (1,2); // 1วิธีการข้างต้นสามารถแก้ปัญหาความต้องการขั้นพื้นฐานได้มากที่สุด แต่เมื่อจำนวนพารามิเตอร์ที่ผ่านไม่แน่นอนวิธีการข้างต้นจะล้มเหลว ในเวลานี้คุณสามารถพิจารณาใช้การสมัครหรือโทร โปรดทราบว่าจำนวนพารามิเตอร์ที่ผ่านที่นี่ไม่แน่นอนดังนั้นจึงเป็นการดีที่สุดที่จะใช้ วิธีนี้มีดังนี้:
ฟังก์ชั่น log () {console.log.apply (คอนโซล, อาร์กิวเมนต์);}; log (1); // 1log (1,2); // 1 2ข้อกำหนดถัดไปคือการเพิ่ม "(แอป)" ออกไปในแต่ละข้อความบันทึกเช่น:
บันทึก ("Hello World"); // (แอพ) Hello Worldจะทำอย่างไรให้หรูหรากว่านี้? ในเวลานี้คุณต้องคิดว่าพารามิเตอร์อาร์กิวเมนต์เป็นอาร์เรย์หลอกซึ่งถูกแปลงเป็นอาร์เรย์มาตรฐานผ่านอาร์เรย์ prototype.slice.call แล้วใช้วิธีอาร์เรย์ที่ไม่มีการปรับเปลี่ยนเช่นนี้:
ฟังก์ชั่น log () {var args = array.prototype.slice.call (อาร์กิวเมนต์); args.unshift ('(แอพ)'); console.log.apply (คอนโซล, args);};ผูกคำอธิบายโดยละเอียด
หลังจากพูดคุยเกี่ยวกับการสมัครและโทรมาพูดคุยเกี่ยวกับการผูก วิธีการ bind () คล้ายกับการใช้และการโทรมากและยังสามารถเปลี่ยนการชี้ของสิ่งนี้ในร่างกายฟังก์ชั่น
คำอธิบายของ MDN คือ: วิธีการ BIND () จะสร้างฟังก์ชั่นใหม่ที่เรียกว่าฟังก์ชั่นการเชื่อมโยง เมื่อเรียกใช้ฟังก์ชั่นการเชื่อมโยงนี้ฟังก์ชั่นการเชื่อมโยงจะใช้พารามิเตอร์แรกของวิธีการ bind () เมื่อมันถูกสร้างขึ้นเป็นสิ่งนี้และพารามิเตอร์ที่สองของวิธีการ bind () และพารามิเตอร์ที่ตามมาบวกกับพารามิเตอร์ของฟังก์ชันการเชื่อมโยงตัวเองเป็นพารามิเตอร์ของฟังก์ชันดั้งเดิมเพื่อเรียกฟังก์ชันดั้งเดิม
ลองมาดูวิธีการใช้งาน ในโหมดโมโนเมอร์ทั่วไปเรามักจะใช้ _ นี่นั่นคือตัวเอง ฯลฯ เพื่อบันทึกสิ่งนี้เพื่อให้เราสามารถอ้างอิงต่อไปหลังจากเปลี่ยนบริบท แบบนี้:
var foo = {bar: 1, eventbind: function () {var _this = this; $ ('. someclass'). on ('คลิก', ฟังก์ชั่น (เหตุการณ์) {/ * กระทำในเหตุการณ์ */console.log (_this.bar); // 1});เนื่องจากกลไกเฉพาะ JavaScript สภาพแวดล้อมบริบทมีการเปลี่ยนแปลงใน EventBind: function () {} เป็น $ ('. someclass') บน ('คลิก', ฟังก์ชั่น (เหตุการณ์) {}) วิธีการข้างต้นในการใช้ตัวแปรเพื่อบันทึกสิ่งนี้มีประโยชน์และไม่มีปัญหา แน่นอนว่าการใช้ bind () สามารถแก้ปัญหานี้ได้อย่างสง่างามยิ่งขึ้น:
var foo = {bar: 1, eventbind: function () {$ ('. someclass'). on ('คลิก', ฟังก์ชั่น (เหตุการณ์) {/ * กระทำในเหตุการณ์ */console.log (this.bar);ในรหัสข้างต้น bind () สร้างฟังก์ชัน เมื่อเหตุการณ์การคลิกนี้ถูกเรียกใช้คำหลักนี้จะถูกตั้งค่าเป็นค่าที่ส่งผ่าน (ที่นี่หมายถึงพารามิเตอร์ที่ส่งผ่านเมื่อ Bind () ถูกเรียก) ดังนั้นที่นี่เราผ่านบริบทที่ต้องการนี้ (จริง ๆ แล้ว foo) ลงในฟังก์ชัน bind () จากนั้นเมื่อฟังก์ชั่นการเรียกกลับถูกเรียกใช้งานนี้จะชี้ไปที่วัตถุ FOO เกาลัดเรียบง่ายอีก:
var bar = function () {console.log (this.x);} var foo = {x: 3} bar (); // undefinedvar func = bar.bind (foo); func (); // 3ที่นี่เราสร้างฟังก์ชั่นใหม่ func เมื่อใช้ bind () เพื่อสร้างฟังก์ชั่นการเชื่อมโยงเมื่อมันถูกดำเนินการมันจะถูกตั้งค่าเป็น foo แทนที่จะเป็นขอบเขตทั่วโลกเช่นเมื่อเราเรียกแถบ ()
มีคำถามที่น่าสนใจ ถ้า bind () เป็นสองเท่าในแถวหรือ bind () คือสามครั้งในแถวแล้วค่าเอาต์พุตคืออะไร? แบบนี้:
var bar = function () {console.log (this.x);} var foo = {x: 3} var sed = {x: 4} var func = bar.bind (foo). -bind (sed); func (); //? var fiv = {x: 5} var func = bar.bind (foo). -bind (sed). -bind (fiv); func (); //? var fiv = {x: 5} var func = bar.bind (foo). -bind (sed). -bind (fiv); func (); -คำตอบคือทั้งสองครั้งจะยังคงออก 3 แทนที่จะเป็น 4 และ 5 ที่คาดหวังเหตุผลก็คือใน JavaScript, Bind () หลายครั้งไม่ถูกต้อง ด้วยเหตุผลที่ลึกซึ้งยิ่งขึ้นการใช้ BIND () นั้นเทียบเท่ากับการใช้ฟังก์ชั่นเพื่อห่อการโทร / ใช้ภายใน การผูกที่สอง () เทียบเท่ากับการห่อผูกแรก () อีกครั้งดังนั้นการผูกหลังจากครั้งที่สองไม่สามารถมีผลได้
สมัครโทรผูกมัดการเปรียบเทียบ
แล้วความแตกต่างและความแตกต่างระหว่างการสมัครโทรและผูกคืออะไร? เมื่อใดควรใช้การใช้งานโทรและเมื่อใดควรใช้ BIND เกาลัดเรียบง่าย:
var obj = {x: 81,}; var foo = {getx: function () {return this.x;}} console.log (foo.getx.bind (obj) ()); //81console.log(foo.getx.call(obj)); //81console.log(foo.getx.apply(obj)); //81console.log(foo.getx.apply(obj)); //81console.log(foo.getx.apply(obj)); // 81เอาต์พุตทั้งสามคือ 81 แต่ให้ความสนใจกับวิธีการโดยใช้วิธี BIND () ซึ่งมีตัวยึดมากขึ้นหลังจากนั้น
นั่นคือความแตกต่างคือเมื่อคุณต้องการเปลี่ยนบริบทไม่ดำเนินการทันที แต่การเรียกกลับใช้วิธีการ bind () ใช้/โทรดำเนินการฟังก์ชั่นทันที
สรุปอีกครั้ง:
•ใช้การโทรผูกทั้งหมดจะใช้เพื่อเปลี่ยนการชี้ของวัตถุนี้ของฟังก์ชัน
•พารามิเตอร์แรกของการใช้การโทรและการผูกคือวัตถุที่ต้องการชี้ไปที่นั่นคือบริบทที่คุณต้องการระบุ
•ใช้การโทรและการผูกสามารถใช้พารามิเตอร์ที่ตามมาเพื่อผ่านพารามิเตอร์
•การผูกส่งคืนฟังก์ชั่นที่เกี่ยวข้องซึ่งง่ายต่อการโทรในภายหลัง สมัครและโทรถูกเรียกทันที
ด้านบนคือการใช้งานที่ชาญฉลาดของการใช้การโทรและการผูกใน JavaScript แนะนำให้คุณรู้จักโดยบรรณาธิการ ฉันหวังว่ามันจะเป็นประโยชน์กับคุณ หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับคุณทันเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!