คำนำ
ฉันเห็นคำถามเช่นนี้ใน SegmentFault:
var f = function () {}; object.prototype.a = function () {}; function.prototype.b = function () {}; var f = new f ();ถาม: F สามารถรับ A และ B ได้หรือไม่? หลักการคืออะไร?
เมื่อมองแวบแรกฉันสับสนจริงๆ หลังจากการศึกษาอย่างรอบคอบฉันพบว่าฉันยังไม่เข้าใจต้นแบบอย่างละเอียดดังนั้นฉันจึงสรุปและเติมในหลุม ~
ฟังก์ชั่นและวัตถุ
ก่อนที่จะแก้ปัญหาให้พูดคุยเกี่ยวกับต้นแบบห่วงโซ่ต้นแบบและความสัมพันธ์ระหว่างฟังก์ชั่นและวัตถุซึ่งเป็นจุดสนใจของบทความนี้
ต้นแบบ
เมื่อสร้างฟังก์ชั่นวัตถุต้นแบบจะถูกสร้างขึ้นโดยอัตโนมัติซึ่งสามารถเข้าถึงได้ผ่านคุณสมบัติต้นแบบของฟังก์ชั่น
สร้างวัตถุอินสแตนซ์ของตัวสร้างซึ่งจะมีตัวชี้ (คุณสมบัติภายใน) อยู่ข้างในชี้ไปที่วัตถุต้นแบบของตัวสร้าง ECMA-262 รุ่นที่ 5 ของตัวชี้นี้เรียกว่า [[ต้นแบบ]] แม้ว่าจะไม่มีวิธีมาตรฐานในการเข้าถึง [[ต้นแบบ]] ในสคริปต์, Firefox, Safari และ Chrome สนับสนุนคุณสมบัติ __proto__ บนวัตถุแต่ละชิ้นเพื่อเข้าถึงวัตถุต้นแบบของตัวสร้าง
ให้ฉันพูดอะไรที่สำคัญอีกครั้ง:
ตัวสร้างเข้าถึงวัตถุต้นแบบผ่านคุณสมบัติต้นแบบ
วัตถุอินสแตนซ์เข้าถึงวัตถุต้นแบบผ่านแอตทริบิวต์ภายใน [[ต้นแบบ]] และเบราว์เซอร์ใช้แอตทริบิวต์ _proto_ สำหรับวัตถุอินสแตนซ์เพื่อเข้าถึงวัตถุต้นแบบ
var f = function () {}; var f = new f (); // สมมติว่าวัตถุต้นแบบของ f คือ p, จากนั้น // f.prototype === p; // f .__ proto__ === p;ทำซ้ำอีกครั้ง - ต้นแบบหมายถึงความสัมพันธ์ระหว่างตัวสร้างและวัตถุต้นแบบและ __proto__ หมายถึงความสัมพันธ์ระหว่างวัตถุอินสแตนซ์และวัตถุต้นแบบ
ห่วงโซ่ต้นแบบ
Class A สืบทอด B, B สืบทอด C ... ในความเป็นจริงมีวัตถุต้นแบบที่มีตัวชี้ชี้ไปที่ B ในวัตถุต้นแบบของ A และวัตถุต้นแบบที่มีตัวชี้ชี้ไปที่ C ในวัตถุต้นแบบ ... โปรดทราบว่าเป็นการเชื่อมต่อระหว่างวัตถุต้นแบบ ไม่มีความสัมพันธ์ระหว่างตัวสร้างทั้งสามของ ABC ดังนั้นจึงเรียกว่า "ห่วงโซ่ต้นแบบ" ~
สมมติว่า A เป็นวัตถุอินสแตนซ์ของ A ห่วงโซ่ต้นแบบของ A จะแสดงในเส้นสีม่วงในรูปด้านล่างและเส้นสีส้มเชื่อมต่อคอนสตรัคเตอร์และวัตถุต้นแบบ
ดังที่เห็นได้จากรูปจุดสิ้นสุดของห่วงโซ่ต้นแบบคือ Object.prototype .__ Proto__ นั่นคือ Null เมื่อมองหาคุณสมบัติหรือวิธีการของ A ให้มองหาว่าตัวเองมีหรือไม่ หากไม่ได้ค้นหาตามห่วงโซ่ต้นแบบจนกว่าจะพบหรือในที่สุดก็กลับไปที่ไม่ได้กำหนดหลังจาก NULL
ฟังก์ชั่นและวัตถุ
ความสัมพันธ์ระหว่างฟังก์ชั่นและวัตถุมีการพันกันเล็กน้อย:
วัตถุเป็นตัวสร้าง เนื่องจากเป็นฟังก์ชันจึงเป็นวัตถุอินสแตนซ์ของฟังก์ชัน ฟังก์ชั่นเป็นตัวสร้าง แต่ function.prototype เป็นวัตถุ เนื่องจากเป็นวัตถุมันเป็นวัตถุอินสแตนซ์ของวัตถุ
วัตถุทั้งหมดเป็นอินสแตนซ์ของวัตถุและฟังก์ชั่นทั้งหมดเป็นอินสแตนซ์ของฟังก์ชัน
วัตถุเป็นอินสแตนซ์ของฟังก์ชั่นและฟังก์ชัน prototype เป็นอินสแตนซ์ของวัตถุ
ความสัมพันธ์ระหว่างทั้งสองจะแสดงในรูปด้านล่าง
ดังที่เห็นได้วัตถุเป็นตัวสร้างมันมีแอตทริบิวต์ต้นแบบที่ชี้ไปที่ Object.prototype และเป็นวัตถุอินสแตนซ์มันมีวัตถุ. __ proto__ ชี้ไปที่ฟังก์ชัน prototype ฟังก์ชั่นเป็นตัวสร้างมันมีแอตทริบิวต์ต้นแบบที่ชี้ไปที่ฟังก์ชัน prototype และฟังก์ชั่นเป็นฟังก์ชั่นและมันก็เป็นอินสแตนซ์ของฟังก์ชันดังนั้นจึงมีฟังก์ชั่น.
สามารถตรวจสอบได้ภายใต้คอนโซลโครเมี่ยมดังแสดงในรูป
การวิเคราะห์คำถามดั้งเดิม
วิธีที่ดีที่สุดในการแก้ปัญหาห่วงโซ่ต้นแบบคือการวาดภาพ หลังจากการวิเคราะห์ก่อนหน้านี้ภาพนี้ไม่ควรเป็นปัญหาดังนี้ ~
ห่วงโซ่ต้นแบบของ F ถูกวาดโดยเส้นสีน้ำเงินดังนั้น F สามารถเข้าถึง A ได้ แต่ B ไม่สามารถเข้าถึงได้
หากคุณไม่วาดภาพในตอนแรกคุณอาจคิดว่า F สามารถเข้าถึงได้ มันอาจจะเป็นเหมือนฉันที่ f.prototype ชี้ไปที่ function.prototype แต่ในความเป็นจริง f.prototype เป็นวัตถุมากกว่าฟังก์ชั่นดังนั้นวัตถุต้นแบบของมันจะไม่เป็นฟังก์ชัน prototype
ดังนั้นคุณควรวาดภาพเมื่อใดก็ตามที่ปัญหาห่วงโซ่ต้นแบบคือ ~
หัวข้อขยาย
ในคำถามข้างต้น F สามารถเข้าถึง A แต่ไม่ใช่ b แต่ F สามารถเข้าถึงทั้ง A และ B หากคุณปรับเปลี่ยนคำถามเป็นสิ่งต่อไปนี้ผลลัพธ์ของ FB () คืออะไร? ทำไม คุณสามารถคิดเกี่ยวกับมัน ~
var f = function () {}; object.prototype.a = function () {}; function.prototype.b = function () {console.log ('f .__ proto__')}; f.prototype.b = function () {console.log ('f.prototype');};สรุป
หลังจากอ่านสิ่งนี้คุณพบคุณสมบัติพิเศษของฟังก์ชั่นหรือไม่?
สำหรับวัตถุทั่วไปมีแอตทริบิวต์ __proto__ เพียงหนึ่งแอตทริบิวต์ที่ใช้ในการเข้าถึงวัตถุต้นแบบของตัวสร้างและสำหรับฟังก์ชั่นมันเป็นทั้งฟังก์ชันและวัตถุ
ในฐานะที่เป็นฟังก์ชั่นมันเกิดมาพร้อมกับแอตทริบิวต์ต้นแบบที่ชี้ไปที่ชื่อฟังก์ชันวัตถุต้นแบบของมัน prototype
เป็นวัตถุอินสแตนซ์ของฟังก์ชันมันมีแอตทริบิวต์ __proto__ ที่ชี้ไปที่ function.prototype
โดยปกติแล้วคุณสมบัติทั้งสองนี้ชี้ไปที่วัตถุสองชิ้น แต่คุณสมบัติทั้งสองของฟังก์ชั่นชี้ไปที่เดียวกันทั้งสองชี้ไปที่ฟังก์ชัน prototype
สำหรับฟังก์ชั่น A () วิธีการใน A.Prototype นั้นมีไว้สำหรับการโทรไปยังวัตถุอินสแตนซ์และจะไม่ถูกใช้ด้วยตัวเอง เมื่อ A เรียกใช้เป็นอินสแตนซ์วิธีการใน A.__ Proto__ จะถูกเรียก กล่าวอีกนัยหนึ่งเมื่อใช้เป็นตัวสร้างห่วงโซ่ A.Prototype จะถูกนำมาใช้และวิธีการและคุณลักษณะจะถูกกำหนดให้กับตัวอย่างของพวกเขา; เมื่อใช้เป็นวัตถุจะใช้โซ่ A .__ Proto__ ในสถานการณ์ที่แตกต่างกันมันไม่ผิดที่จะแยกแยะตัวตนของมัน
หลังจากบทความทั้งหมดฉันรู้สึกว่าสิ่งที่ฉันพูดนั้นค่อนข้างจู้จี้ ... โปรดแก้ไขฉันหากมีข้อบกพร่องใด ๆ ~ สำหรับคำถามฉันไม่รู้ว่าจะเรียกมันว่าอะไร -
ขอให้บทความนี้นำมาให้คุณได้รับหลังจากอ่าน ~ ^_ ^
ขอบคุณสำหรับการสนับสนุนเว็บไซต์นี้ เราจะอัปเดตข้อมูลที่เกี่ยวข้องต่อไปในอนาคตเพื่อช่วยให้คุณเรียนรู้และเข้าใจส่วนนี้ของความรู้!