มีความสัมพันธ์มากมายและวุ่นวายใน JavaScript ห่วงโซ่ขอบเขตเป็นความสัมพันธ์แบบโซ่ทางเดียวซึ่งค่อนข้างง่ายและชัดเจน ความสัมพันธ์การโทรของกลไกนี้ค่อนข้างซับซ้อน และสำหรับต้นแบบมันเป็นความสัมพันธ์สามเหลี่ยมระหว่างต้นแบบโปรโตและคอนสตรัคเตอร์ บทความนี้ใช้ภาพแรกเพื่อชี้แจงความหมายจากนั้นอธิบายความสัมพันธ์สามเหลี่ยมของต้นแบบโดยละเอียด
ภาพประกอบ
แนวคิด
ความสัมพันธ์ที่ซับซ้อนในภาพด้านบนจริง ๆ มาจากรหัสสองบรรทัด
function foo () {}; var f1 = new foo;【คอนสตรัคเตอร์】
ฟังก์ชั่นที่ใช้ในการเริ่มต้นวัตถุที่สร้างขึ้นใหม่คือตัวสร้าง ในตัวอย่างฟังก์ชั่น foo () เป็นตัวสร้าง
【วัตถุอินสแตนซ์】
วัตถุที่สร้างขึ้นโดยการดำเนินการใหม่ของตัวสร้างเป็นวัตถุอินสแตนซ์ คุณสามารถใช้ตัวสร้างหนึ่งตัวเพื่อสร้างวัตถุอินสแตนซ์หลายรายการ
function foo () {}; var f1 = new foo; var f2 = new foo; console.log (f1 === f2); // false【วัตถุต้นแบบและต้นแบบ】
ตัวสร้างมีคุณสมบัติต้นแบบที่ชี้ไปที่วัตถุต้นแบบของวัตถุอินสแตนซ์ วัตถุหลายชิ้นที่สร้างอินสแตนซ์โดยตัวสร้างเดียวกันมีวัตถุต้นแบบเดียวกัน ใช้วัตถุต้นแบบเป็นประจำเพื่อให้ได้มรดก
ฟังก์ชัน foo () {}; foo.prototype.a = 1; var f1 = new foo; var f2 = ใหม่ foo; console.log (foo.prototype.a); // 1console.log (f1.a); // 1console.log (f2.a);【คอนสตรัคเตอร์】
วัตถุต้นแบบมีแอตทริบิวต์ตัวสร้างที่ชี้ไปที่ฟังก์ชันตัวสร้างที่สอดคล้องกับวัตถุต้นแบบ
function foo () {}; console.log (foo.prototype.constructor === foo); // trueเนื่องจากวัตถุอินสแตนซ์สามารถสืบทอดคุณสมบัติของวัตถุต้นแบบวัตถุอินสแตนซ์จึงมีแอตทริบิวต์ตัวสร้างซึ่งชี้ไปที่ฟังก์ชันตัวสร้างที่สอดคล้องกับวัตถุต้นแบบ
function foo () {}; var f1 = new foo; console.log (f1.constructor === foo); // true【โปรโต】
วัตถุอินสแตนซ์มีแอตทริบิวต์โปรโตที่ชี้ไปที่วัตถุต้นแบบที่สอดคล้องกับวัตถุอินสแตนซ์
function foo () {}; var f1 = new foo; console.log (f1 .__ proto__ === foo.prototype); // trueอธิบาย
แนวคิดได้รับการแนะนำและตอนนี้เราจะอธิบายความสัมพันธ์ในรายละเอียด
function foo () {}; var f1 = new foo;【ตอนที่ 1: foo 】
วัตถุอินสแตนซ์ F1 ถูกสร้างขึ้นโดยการดำเนินการใหม่ของ Constructor Foo () วัตถุต้นแบบของตัวสร้าง foo () คือ foo.prototype; วัตถุอินสแตนซ์ F1 ยังชี้ไปที่วัตถุต้นแบบ foo.prototype ผ่านแอตทริบิวต์ __proto__
function foo () {}; var f1 = new foo; console.log (f1 .__ proto === foo.prototype); // trueวัตถุอินสแตนซ์ F1 นั้นไม่มีแอตทริบิวต์ตัวสร้าง แต่สามารถสืบทอดแอตทริบิวต์ตัวสร้างของวัตถุต้นแบบ foo.prototype
function foo () {}; var f1 = new foo; console.log (foo.prototype.constructor === foo); // trueconsole.log (f1.constructor === foo); // trueconsole.log (f1.hasownpropertyรูปต่อไปนี้แสดงเอฟเฟกต์คอนโซลของวัตถุอินสแตนซ์ F1
【ส่วนที่ 2: วัตถุ】
Foo.prototype เป็นวัตถุต้นแบบของ F1 และยังเป็นวัตถุอินสแตนซ์ ในความเป็นจริงวัตถุใด ๆ สามารถถือได้ว่าเป็นวัตถุที่สร้างอินสแตนซ์ผ่านการดำเนินการใหม่ของตัวสร้างวัตถุ () ดังนั้น foo.prototype เป็นวัตถุอินสแตนซ์ตัวสร้างของมันคือ Object () และวัตถุต้นแบบคือ Object.prototype ดังนั้นคุณสมบัติต้นแบบของวัตถุสร้าง () ชี้ไปที่วัตถุวัตถุต้นแบบ คุณสมบัติโปรโตของวัตถุอินสแตนซ์ foo.prototype ยังชี้ไปที่วัตถุวัตถุต้นแบบ
function foo () {}; var f1 = new foo; console.log (foo.prototype .__ proto__ === object.prototype); // trueวัตถุอินสแตนซ์ foo.prototype เองมีแอตทริบิวต์ตัวสร้างดังนั้นจึงแทนที่แอตทริบิวต์ตัวสร้างที่สืบทอดมาจากวัตถุวัตถุต้นแบบ prototype
function foo () {}; var f1 = new foo; console.log (foo.prototype.constructor === foo); // trueconsole.log (object.prototype.constructor === Object); // TrueConsole.log (foo.prototype.hasownproperty ('Constructor')); // trueconsole.log (foo.prototype.hasownproperty ('constructor'));รูปต่อไปนี้แสดงเอฟเฟกต์คอนโซลของวัตถุอินสแตนซ์ foo.prototype
หาก Object.prototype เป็นวัตถุอินสแตนซ์วัตถุต้นแบบคืออะไร? ผลลัพธ์คือโมฆะ ฉันคิดว่านี่อาจเป็นผลมาจาก typeof null ซึ่งเป็นหนึ่งในเหตุผลว่าทำไม 'วัตถุ'
console.log (object.prototype .__ proto__ === null); // true
【ส่วนที่ 3: ฟังก์ชั่น】
ดังที่ได้กล่าวไว้ก่อนหน้านี้ฟังก์ชั่นเป็นวัตถุ แต่วัตถุที่มีฟังก์ชั่นพิเศษ ฟังก์ชั่นใด ๆ สามารถถือได้ว่าเป็นผลมาจากการสร้างอินสแตนซ์ผ่านการดำเนินการใหม่ของตัวสร้างฟังก์ชัน ()
หากฟังก์ชั่น foo ได้รับการยกย่องว่าเป็นวัตถุอินสแตนซ์ตัวสร้างของมันคือฟังก์ชัน () และวัตถุต้นแบบของมันคือฟังก์ชัน prototype; ในทำนองเดียวกันตัวสร้างของวัตถุฟังก์ชั่นก็เป็นฟังก์ชัน () และวัตถุต้นแบบของมันคือฟังก์ชัน prototype
function foo () {}; var f1 = new foo; console.log (foo .__ proto__ === function.prototype); // trueconsole.log (วัตถุ.แอตทริบิวต์ตัวสร้างของฟังก์ชันวัตถุต้นแบบ prototype ชี้ไปที่ฟังก์ชันตัวสร้าง (); วัตถุวัตถุอินสแตนซ์และฟูไม่มีแอตทริบิวต์ตัวสร้างและจำเป็นต้องสืบทอดแอตทริบิวต์ตัวสร้างของฟังก์ชันวัตถุต้นแบบ prototype
function foo () {}; var f1 = new foo; console.log (function.prototype.constructor === ฟังก์ชั่น); // trueconsole.log (foo.constructor === ฟังก์ชั่น); // trueconsole.log (foo.hasownproperty ฟังก์ชั่น); // trueconsole.log (object.hasownproperty ('constructor')); // falseฟังก์ชั่นทั้งหมดถือได้ว่าเป็นวัตถุอินสแตนซ์ของการทำงานใหม่ของฟังก์ชันคอนสตรัคเตอร์ () จากนั้นฟังก์ชั่นสามารถถือได้ว่าเป็นผลมาจากการเรียกใช้อินสแตนซ์การดำเนินการใหม่ของตัวเอง
ดังนั้นหากฟังก์ชั่นเป็นวัตถุอินสแตนซ์ตัวสร้างคือฟังก์ชั่นและวัตถุต้นแบบของมันคือฟังก์ชัน prototype
console.log (ฟังก์ชั่น .__ proto__ === function.prototype); // trueconsole.log (function.prototype.constructor === ฟังก์ชั่น); // trueconsole.log (function.prototype ===
หาก function.prototype เป็นวัตถุอินสแตนซ์วัตถุต้นแบบคืออะไร? ก่อนหน้านี้วัตถุทั้งหมดถือได้ว่าเป็นผลการสร้างอินสแตนซ์ของการทำงานใหม่ของตัวสร้างวัตถุ () ดังนั้นวัตถุต้นแบบของ function.prototype คือ Object.prototype และฟังก์ชันต้นแบบคือวัตถุ ()
console.log (function.prototype .__ proto__ === object.prototype); // true
ส่วนที่สองแนะนำว่าวัตถุต้นแบบของ Object.prototype เป็นโมฆะ
console.log (object.prototype .__ proto__ === null); // true
สรุป
【 1 】ฟังก์ชั่น (ฟังก์ชั่นเป็นฟังก์ชัน) เป็นผลลัพธ์ของฟังก์ชั่นใหม่ดังนั้นฟังก์ชันสามารถใช้เป็นวัตถุอินสแตนซ์ตัวสร้างของมันคือฟังก์ชัน () และวัตถุต้นแบบคือฟังก์ชัน prototype
【 2 】วัตถุ (ฟังก์ชั่นเป็นวัตถุ) เป็นผลลัพธ์ของวัตถุใหม่ดังนั้นวัตถุสามารถใช้เป็นวัตถุอินสแตนซ์ตัวสร้างของมันคือวัตถุ () และวัตถุต้นแบบคือวัตถุ prototype
【 3 】 Object.prototype วัตถุต้นแบบเป็นโมฆะ