มรดกใน JavaScript ค่อนข้างแปลก มันไม่สามารถใช้การสืบทอดอินเตอร์เฟสและสามารถพึ่งพาการสืบทอดต้นแบบเท่านั้น
ห่วงโซ่ต้นแบบ
ต้นแบบเป็นวัตถุ อินสแตนซ์ที่สร้างขึ้นผ่านตัวสร้างจะมีตัวชี้ไปยังต้นแบบเพื่อให้ได้คุณสมบัติและวิธีการของต้นแบบ ด้วยวิธีนี้วัตถุอินสแตนซ์มีวิธีแอตทริบิวต์ของตัวสร้างและวิธีแอตทริบิวต์ของต้นแบบจากนั้นชี้ให้เห็นต้นแบบของตัวสร้างที่ต้องสืบทอดไปยังอินสแตนซ์นี้เพื่อให้วิธีการทั้งหมดของอินสแตนซ์สามารถสืบทอดได้
ดูรหัสสาธิตต่อไปนี้:
// ประกาศ superclass เพิ่มคุณสมบัติและวิธีการที่เกี่ยวข้องผ่านฟังก์ชั่น constructors และ prototypes super () {this.property = true;} super.prototype.getSuperValue = function () {ส่งคืนนี้ subclass ไปยังอินสแตนซ์ของ superclass และรับทุกอย่างใน subyclass subtype.prototype = new super (); subtype.prototype.constructor = subtype; subtype.prototype.getSubValue = function () อินสแตนซ์ = ใหม่ชนิดย่อย (); console.log (instance.getSuperValue ());ต้นแบบเริ่มต้นของฟังก์ชั่นทั้งหมดเป็นอินสแตนซ์ของวัตถุดังนั้นต้นแบบเริ่มต้นจะมีตัวชี้ภายในไปยัง Object.prototype
ใช้อินสแตนซ์ของและ isprototypeof เพื่อกำหนดความสัมพันธ์ระหว่างต้นแบบและอินสแตนซ์:
อินสแตนซ์อินสแตนซ์ของวัตถุ; object.prototype.isprototypeof (อินสแตนซ์);
เมื่อใช้โซ่ต้นแบบคุณต้องกำหนดวิธีอย่างระมัดระวัง คลาสย่อยจำเป็นต้องเขียนวิธีหรือการขยายของ supertype ใหม่และจะต้องวางหลังจากคำสั่งที่แทนที่ต้นแบบเพื่อให้สามารถมีผล นอกจากนี้เมื่อสืบทอดผ่านห่วงโซ่ต้นแบบคุณไม่สามารถใช้ตัวอักษรวัตถุเพื่อสร้างวิธีการต้นแบบซึ่งจะแทนที่ห่วงโซ่ต้นแบบ:
...... subtype.prototype = new super (); subtype.prototype = {.... };สิ่งนี้จะแทนที่ตัวชี้เพื่อชี้ไปที่วัตถุใหม่เขียนใหม่ห่วงโซ่ต้นแบบ
วิธีการสืบทอดของโซ่ต้นแบบมีข้อบกพร่องและมีสองปัญหาหลัก:
1. จากต้นแบบที่มีค่าประเภทอ้างอิงมันจะถูกแชร์โดยทุกกรณี
ดังที่ได้กล่าวไว้ในบทความก่อนหน้านี้แอตทริบิวต์ต้นแบบที่มีค่าประเภทอ้างอิงจะถูกแชร์โดยทุกกรณี อินสแตนซ์หนึ่งจะได้รับการแก้ไขและอินสแตนซ์อื่น ๆ จะเปลี่ยนไปตามลำดับ ดังนั้นคุณลักษณะจะต้องกำหนดในตัวสร้าง เมื่อห่วงโซ่ต้นแบบสืบทอดไม่ว่าแอตทริบิวต์ใน superclass จะถูกกำหนดไว้ในตัวสร้างหรือต้นแบบทั้งหมดจะกลายเป็นวัตถุอินสแตนซ์และได้รับการสืบทอดโดยคลาสย่อยดังนั้นจึงมีผลกระทบต่ออินสแตนซ์ของคลาสย่อย
2. เมื่อสร้างอินสแตนซ์ของชนิดย่อยพารามิเตอร์ไม่สามารถส่งผ่านไปยังตัวสร้าง Supertype
การสืบทอดของห่วงโซ่ต้นแบบชี้ไปที่ต้นแบบ subclass โดยตรงไปยังอินสแตนซ์ของ superclass และในเวลานี้พารามิเตอร์สามารถส่งผ่านไปยัง superclass อย่างไรก็ตามเมื่อ subclass สร้างอินสแตนซ์มันสามารถส่งผ่านพารามิเตอร์ไปยังตัวสร้างของคลาสย่อยเท่านั้น แต่ไม่ใช่ตัวสร้างของซูเปอร์คลาส
ดังนั้นในการใช้งานจริงโซ่ต้นแบบจึงไม่ค่อยใช้เพียงอย่างเดียว
แนวทางปฏิบัติของรหัสที่เกี่ยวข้อง
ระบุแอตทริบิวต์ต้นแบบ
ฟังก์ชั่น HASPROTOTYPEPROPERTY (วัตถุ, ชื่อ) {ส่งคืนชื่อใน OBJECT &&! Object.hasownProperty (ชื่อ);}ใช้วัตถุต้นแบบในตัวสร้าง
ฟังก์ชันบุคคล (ชื่อ) {this.name = name;} person.prototype = {constructor: person, sayname: function () {console.log (this.name); }, toString: function () {}}; var person1 = บุคคลใหม่ ('nicholas'); var person2 = บุคคลใหม่ ('greg); console.log (บุคคลที่เป็นตัวอย่างของบุคคล); // trueconsole.log (person1.constructor === บุคคล); // trueconsole.log (person1.constructor === บุคคล); // trueconsole.log (person1.constructor === วัตถุ); // falseconsole.log (person2 instanceof person); // trueconsole.log (person2.constructor === บุคคล); // trueconsole.log (person2.constructor === วัตถุ); // เท็จการสืบทอดวัตถุ
var person1 = {ชื่อ: 'nicholas', sayname: function () {console.log (this.name); }}; var person2 = object.create (person1, {ชื่อ: {กำหนดค่าได้: จริง, enumerable: จริง, ค่า: 'greg', เขียนได้: จริง}}); person1.sayname (); // nicholasperson2.sayname (); // gregconsole.log (person1.hasownproperty ('sayname')); // trueconsole.log (person1.ispropertyof (person2)); // trueconsole.log (person2.hasownproperty ('sayname')); // เท็จโหมดโมดูล
var person = (function () {var Age = 25; function getage () {return age;} function growolder () {age ++;} return {ชื่อ: 'nicholas', getage: getage, growolder: growolder};} ());ตัวสร้างขอบเขต
ฟังก์ชันบุคคล (ชื่อ) {this.name = name;} person.prototype.sayname = function () {console.log (this.name);}; var person1 = บุคคล ('nicholas'); console.log (บุคคล // falseconsole.log (typeof person1); // undefinedConsole.log (ชื่อ); // นิโคลัส