บทความนี้อธิบายกลไกการสืบทอด JavaScript แบ่งปันสำหรับการอ้างอิงของคุณ การวิเคราะห์เฉพาะมีดังนี้:
โดยทั่วไปเป็นเรื่องยากสำหรับผู้เริ่มต้นที่จะเข้าใจกลไกการสืบทอดของภาษาจาวาสคริปต์ มันไม่มีแนวคิดของ "คลาสย่อย" และ "คลาสแม่" และไม่มีความแตกต่างระหว่าง "คลาส" และ "อินสแตนซ์" มันขึ้นอยู่กับแบบจำลอง "ห่วงโซ่ต้นแบบ" ที่แปลกมากเพื่อให้ได้มรดก
ฉันใช้เวลามากมายในการศึกษาส่วนนี้และจดบันทึกจำนวนมาก แต่พวกเขาทั้งหมดเป็นหน่วยความจำที่ถูกบังคับและไม่สามารถเข้าใจได้โดยพื้นฐาน
1. วิธีสร้างคลาส
สมมติว่ามีชั้นเรียนที่เรียกว่าบุคคลดังนี้:
คัดลอกรหัสดังนี้: var person = function (ชื่อ, อายุ) {
this.name = ชื่อ;
this.age = อายุ;
-
person.prototype.getName = function () {
ส่งคืนสิ่งนี้ชื่อ;
-
ดังที่ได้กล่าวไว้ข้างต้น: บุคคลแสดงถึงทุกคนบนโลกและทุกคนมีคุณลักษณะพื้นฐานสองประการนี้: ชื่อและอายุ; ตอนนี้เราต้องการใช้ชั้นเรียนนักเรียนแล้วเราก็รู้ นักเรียนยังเป็นบุคคลและนักเรียนก็มีคุณลักษณะเช่นชื่อและอายุ คำถามตอนนี้คือเราจะสร้างความสัมพันธ์นี้ได้อย่างไร?
ก่อนอื่นให้ดูว่าภาษาที่มุ่งเน้นวัตถุบริสุทธิ์ทำอย่างไร (เช่น ActionsScript3)
คัดลอกรหัสดังนี้: นักเรียนชั้นเรียนขยายบุคคล {}; // มันง่ายมากรหัสหนึ่งบรรทัด; จะแม่นยำยิ่งขึ้นหนึ่งคำ-ขยาย
2. ฉันจะทำอย่างไรถ้าฉันเปลี่ยนเป็น JS
ก่อนที่จะอธิบายการใช้งานกลไกการสืบทอด JS ก่อนอื่นให้เข้าใจห่วงโซ่ต้นแบบของ JS:
การคัดลอกรหัสมีดังนี้: var person = บุคคลใหม่ ('poised-flw', 21);
person.getName (); // "Poised-flw"
สำหรับวิธีการ getName () ข้างต้นมันถูกดำเนินการอย่างไร? ก่อนอื่นคุณจะพบว่ามีวิธี getName () ในฟังก์ชันบุคคลและไม่พบหรือไม่ จากนั้นไปที่ Person.prototype เพื่อค้นหาและค้นหาว่ามี! จากนั้นเรียกมันว่าจะเกิดอะไรขึ้นถ้ามันไม่? ดำเนินการต่อเพื่อทำตามวิธีเดียวกันและค้นหาตามต้นแบบจนกว่าคุณจะพบวิธีการหรือไปถึงด้านบนของห่วงโซ่ต้นแบบ!
ตัวอย่างเช่นขณะนี้มีตัวสร้างที่เรียกว่า Dog ที่แสดงถึงต้นแบบของวัตถุสุนัข
คัดลอกรหัสดังนี้: ฟังก์ชั่นสุนัข (ชื่อ) {
this.name = ชื่อ;
-
การใช้ใหม่สำหรับตัวสร้างนี้จะสร้างอินสแตนซ์ของวัตถุสุนัข
รหัสสำเนามีดังนี้: var doga = สุนัขใหม่ ('ผมใหญ่');
การแจ้งเตือน (doga.name); // ผมใหญ่
ให้ความสนใจกับคำหลักนี้ในตัวสร้างซึ่งแสดงถึงวัตถุอินสแตนซ์ที่สร้างขึ้นใหม่
3. ข้อเสียของผู้ให้บริการใหม่
มีข้อเสียอย่างหนึ่งในการใช้ตัวสร้างเพื่อสร้างวัตถุอินสแตนซ์นั่นคือความสามารถในการแบ่งปันแอตทริบิวต์และวิธีการ
ตัวอย่างเช่นในคอนสตรัคเตอร์ของวัตถุสุนัขตั้งค่าสปีชีส์แอตทริบิวต์ทั่วไปของวัตถุอินสแตนซ์
คัดลอกรหัสดังนี้: ฟังก์ชั่นสุนัข (ชื่อ) {
this.name = ชื่อ;
this.species = 'canidae';
-
จากนั้นมีการสร้างวัตถุอินสแตนซ์สองรายการ:
รหัสสำเนามีดังนี้: var doga = สุนัขใหม่ ('ผมใหญ่');
var dogb = สุนัขใหม่ ('eimao');
คุณลักษณะสปีชีส์ของวัตถุทั้งสองนี้มีความเป็นอิสระการแก้ไขหนึ่งจะไม่ส่งผลกระทบต่อสิ่งอื่น
การคัดลอกรหัสมีดังนี้: doga.species = 'หญิง';
การแจ้งเตือน (dogb.species); // แสดง "ครอบครัวสุนัข" ไม่ได้รับผลกระทบจาก Doga
แต่ละวัตถุอินสแตนซ์มีสำเนาคุณสมบัติและวิธีการของตนเอง สิ่งนี้ไม่เพียง แต่ล้มเหลวในการแบ่งปันข้อมูล แต่ยังเป็นการเสียทรัพยากรจำนวนมาก
ดังนั้น: แนวคิดการสืบทอด: ใช้กลไกการสืบทอดผ่านห่วงโซ่ต้นแบบที่เป็นเอกลักษณ์ของ JS!
4. มรดกตามห่วงโซ่ต้นแบบ
1. การสืบทอดโดยตรงและการดำเนินการ
คัดลอกรหัสดังนี้: var students = function (ชื่อ, อายุ, sid) {
person.call (นี่, ชื่อ, อายุ);
this.sid = sid;
-
นักเรียน. prototype = คนใหม่ (); // ทำให้บุคคลในห่วงโซ่ต้นแบบของนักเรียนใช้กลไกการสืบทอด
นักเรียน. prototype.constructor = นักเรียน;
นักเรียน prototype.getResults = function () {
// รับเกรดของนักเรียน
-
จำเป็นต้องไม่พลาดนักเรียน prototype.constructor = นักเรียนสาย! เมื่อกำหนดคอนสตรัคเตอร์ต้นแบบเริ่มต้นของมันคืออินสแตนซ์ของวัตถุและจากนั้นแอตทริบิวต์ตัวสร้างของต้นแบบจะถูกตั้งค่าเป็นฟังก์ชันโดยอัตโนมัติ! - - หากต้นแบบถูกตั้งค่าด้วยตนเองเป็นวัตถุอื่นวัตถุใหม่จะไม่ได้รับค่าตัวสร้างของวัตถุดั้งเดิมดังนั้นแอตทริบิวต์ตัวสร้างจะต้องรีเซ็ต ชอบ:
คัดลอกรหัสดังนี้: var test = function () {
this.time = "Now";
-
console.log (test.prototype); // วัตถุ {} วัตถุเปล่า
console.log (test.prototype.constructor); // function () {this.time = "now";} และฟังก์ชันเอง
// ถ้าคุณเปลี่ยนคุณสมบัติต้นแบบของการทดสอบด้วยตนเอง
test.prototype = {
Somefunc: function () {
console.log ('Hello World!');
-
-
console.log (test.prototype.constructor); // function object () {[รหัสดั้งเดิม]}
// จากนั้นคุณจะพบว่าการชี้นั้นผิดอย่างสมบูรณ์ดังนั้นเมื่อเปลี่ยนคุณสมบัติต้นแบบด้วยตนเองคุณต้องเปลี่ยนการชี้ตัวสร้าง
หลังจากการทดสอบข้างต้นคุณจะรู้ว่าทำไมคุณต้องปรับเปลี่ยนค่าตัวสร้าง
2. ฟังก์ชั่นที่สืบทอดมา
คัดลอกรหัสดังนี้: ฟังก์ชันขยาย (subclass, superclass) {
var f = function () {};
f.prototype = superclass.prototype;
subclass.prototype = new f ();
subclass.prototype.constructor = subclass;
-
ในความเป็นจริงฟังก์ชั่นของฟังก์ชั่นนี้เป็นเพียงการห่อหุ้มกระบวนการสืบทอดด้านบนและความแตกต่างคือ:
มันสืบทอดเฉพาะแอตทริบิวต์ต้นแบบของ superclass และไม่ได้สืบทอดแอตทริบิวต์ในคอนสตรัคเตอร์ superclass;
ข้อดีของสิ่งนี้คือการลดค่าใช้จ่ายของตัวสร้างใหม่!
แน่นอนปัญหาที่ตามมาคือคุณไม่สามารถผ่านฟังก์ชั่นนี้เพื่ออนุญาตให้คลาสย่อยสามารถสืบทอดคุณสมบัติทั้งหมดของ superclass
ทำให้ดีขึ้น:
คัดลอกรหัสดังต่อไปนี้: // ดำเนินการต่อเพื่อเพิ่มบรรทัดของรหัสไปยังตัวสร้างนักเรียน:
person.call (นี่, ชื่อ, อายุ);
5. สรุป
การใช้หลักการลูกโซ่ต้นแบบของ JS เราสามารถใช้กลไกการสืบทอด JS ได้อย่างง่ายดาย แม้ว่ามันจะไม่เข้มงวดมาก แต่เป้าหมายของฉันก็ประสบความสำเร็จ: พยายามปรากฏรหัสซ้ำ ๆ ครั้งเดียว!
ฉันหวังว่าบทความนี้จะเป็นประโยชน์กับการเขียนโปรแกรม JavaScript ของทุกคน