การใช้รหัสซ้ำและหลักการของมัน
代码复用ตามชื่อที่แนะนำคือนำกลับมาใช้ใหม่หรือแม้แต่รหัสทั้งหมดที่เขียนขึ้นเพื่อสร้างโปรแกรมใหม่ เมื่อพูดถึงการใช้รหัสซ้ำสิ่งแรกที่เรานึกได้คือ继承性หลักการของการใช้รหัสซ้ำคือ:
优先使用对象组合,而不是类继承ใน JS เนื่องจากไม่มีแนวคิดของชั้นเรียนแนวคิดของอินสแตนซ์จึงไม่ได้มีความหมายมากนัก วัตถุใน JS เป็นคู่คีย์-ค่าที่ง่ายซึ่งสามารถสร้างและแก้ไขได้แบบไดนามิก
แต่ใน js เราสามารถยกตัวอย่างวัตถุโดยใช้ตัวสร้างและตัวดำเนินการ new ซึ่งมีความคล้ายคลึงกันทางไวยากรณ์กับภาษาการเขียนโปรแกรมอื่น ๆ ที่ใช้คลาส
ตัวอย่างเช่น:
var trigkit4 = new Person(); js ดูเหมือนจะเป็นชั้นเรียนเมื่อเรียก Person สร้าง แต่จริงๆแล้วมันยังคงเป็นฟังก์ชั่นซึ่งทำให้เรามีแนวคิดการพัฒนาและรูปแบบการสืบทอดที่สันนิษฐานว่าเป็นไปตามชั้นเรียนซึ่งเราสามารถเรียกว่า "รูปแบบการสืบทอดคลาสสิก"
แบบจำลองการสืบทอดแบบดั้งเดิมต้องการคำหลักของ class เราคิดว่าแบบจำลองการสืบทอดคลาสข้างต้นเป็น现代继承模式ซึ่งเป็นแบบจำลองที่ไม่จำเป็นต้องพิจารณาในชั้นเรียน
โหมดมรดกคลาสสิก
ดูสองตัวอย่างต่อไปนี้ของตัวสร้าง Parent() และ Child() :
<script type="text/javascript">ฟังก์ชันพาเรนต์ (ชื่อ) {
this.name = name || 'อัลเลน';
-
parent.prototype.say = function () {
ส่งคืนสิ่งนี้ชื่อ;
-
ฟังก์ชั่นเด็ก (ชื่อ) {}
// สร้างวัตถุด้วยตัวสร้างหลักและกำหนดวัตถุให้กับต้นแบบเด็กเพื่อให้ได้มรดก
ฟังก์ชั่นสืบทอด (c, p) {
c.prototype = new p (); // แอตทริบิวต์ต้นแบบควรชี้ไปที่วัตถุไม่ใช่ฟังก์ชัน
-
// เรียกฟังก์ชันที่สืบทอดมา
สืบทอด (เด็กผู้ปกครอง);
</script>
เมื่อวัตถุถูกสร้างขึ้นโดยใช้คำสั่ง new Child() มันจะได้รับฟังก์ชันการทำงานจากอินสแตนซ์ Parent() ผ่านต้นแบบเช่น:
var kid = new Child();kid.say();//Allenห่วงโซ่ต้นแบบ
มาพูดคุยกันว่าโซ่ต้นแบบทำงานอย่างไรในโหมดการสืบทอดคลาส เราคิดว่าวัตถุเป็นบล็อกบางแห่งในหน่วยความจำที่มีข้อมูลและการอ้างอิงไปยังบล็อกอื่น ๆ เมื่อวัตถุถูกสร้างขึ้นโดยใช้คำสั่ง new Parent() บล็อกเช่นนี้ทางด้านซ้ายของรูปด้านล่างจะถูกสร้างขึ้น บล็อกนี้บันทึกแอตทริบิวต์ name หากคุณต้องการเข้าถึงวิธี say() เราสามารถเข้าถึง Parent.prototype __proto__ ทางด้านขวาโดยชี้ไปที่ prototype ของตัวสร้าง Parent()
ดังนั้นจะเกิดอะไรขึ้นเมื่อสร้างวัตถุใหม่กับ var kid = new Child() ? ดังที่แสดงในรูปด้านล่าง:
วัตถุที่สร้างขึ้นโดยใช้คำสั่ง new Child() เกือบจะว่างเปล่ายกเว้นลิงก์โดยนัย __proto__ ในกรณีนี้ __proto__ ชี้ไปที่วัตถุที่สร้างขึ้นโดยใช้คำสั่ง new Parent() ในฟังก์ชั่น inherit()
เมื่อดำเนินการ kid.say() เนื่องจากวัตถุบล็อกในมุมซ้ายล่างไม่มีวิธี say() มันจะสืบค้นวัตถุบล็อกกลางผ่านห่วงโซ่ต้นแบบ อย่างไรก็ตามวัตถุบล็อกกลางยังไม่มีวิธี say() ดังนั้นจึงเป็นไปตามห่วงโซ่ต้นแบบเพื่อสอบถามวัตถุบล็อกขวาสุดและวัตถุเกิดขึ้นเพื่อให้มีวิธี say() เสร็จแล้ว?
การดำเนินการยังไม่เสร็จที่นี่ this.name มีการอ้างอิงในวิธี say() ซึ่งชี้ไปที่วัตถุที่สร้างโดยตัวสร้าง ที่นี่มันชี้ไปที่บล็อก new Child() อย่างไรก็ตามไม่มีแอตทริบิวต์ name ใน new Child() ด้วยเหตุผลนี้บล็อกระดับกลางจะถูกสืบค้นและบล็อกระดับกลางจึงมีแอตทริบิวต์ name เมื่อมาถึงจุดนี้การสืบค้นของห่วงโซ่ต้นแบบเสร็จสมบูรณ์
สำหรับการอภิปรายโดยละเอียดเพิ่มเติมโปรดตรวจสอบบทความของฉัน: บันทึกการเรียนรู้ JavaScript (v) คำอธิบายโดยละเอียดเกี่ยวกับต้นแบบและห่วงโซ่ต้นแบบ
ต้นแบบที่ใช้ร่วมกัน
กฎของรูปแบบนี้คือสมาชิกที่นำกลับมาใช้ใหม่ควรถูกถ่ายโอนไปยังต้นแบบแทนที่จะวางไว้ในสิ่งนี้ ดังนั้นเพื่อจุดประสงค์ในการสืบทอดสิ่งใดก็ตามที่ควรค่าแก่การสืบทอดควรนำไปใช้ในต้นแบบ ดังนั้นคุณสามารถตั้งค่าต้นแบบของวัตถุเด็กและต้นแบบของวัตถุแม่เป็นเช่นเดียวกับตัวอย่างด้านล่าง:
function inherit(C,P){C.prototype = P.Prototype;
-
วัตถุลูกและวัตถุหลักแบ่งปันต้นแบบเดียวกันและสามารถเข้าถึงวิธี say() อย่างเท่าเทียมกัน อย่างไรก็ตามวัตถุเด็กไม่ได้สืบทอดแอตทริบิวต์ name
มรดกต้นแบบ
การสืบทอดต้นแบบเป็นแบบจำลองการสืบทอดแบบไม่มีคลาส "ทันสมัย ดูตัวอย่างต่อไปนี้:
<script type="text/javascript">// วัตถุที่จะสืบทอด
var parent = {
ชื่อ: "Jack" // ไม่มีเครื่องหมายอัฒภาคที่นี่
-
//新对象var child = object (parent);
alert(child.name);//Jack</script>
ในโหมดต้นแบบไม่จำเป็นต้องใช้ตัวอักษรวัตถุเพื่อสร้างวัตถุหลัก ดังที่แสดงในรหัสต่อไปนี้คุณสามารถใช้ตัวสร้างเพื่อสร้างวัตถุพาเรนต์ ในการทำเช่นนั้นทั้งคุณสมบัติของตัวเองและคุณสมบัติของต้นแบบของตัวสร้างจะได้รับการสืบทอด
<script type="text/javascript">// ตัวสร้างหลัก
ฟังก์ชั่นบุคคล () {
this.name = "trigkit4";
-
// เพิ่มลงในแอตทริบิวต์ต้นแบบ
person.prototype.getName = function () {
ส่งคืนสิ่งนี้ชื่อ;
-
// สร้างวัตถุคลาสบุคคลใหม่
var obj = คนใหม่ ();
// สืบทอด
var kid = object (obj);
Alert (kid.getName ()); // Trigkit4
</script>
ในโหมดนี้คุณสามารถเลือกที่จะสืบทอดเฉพาะวัตถุต้นแบบที่มีอยู่ในตัวสร้างที่มีอยู่ วัตถุที่สืบทอดมาจากวัตถุโดยไม่คำนึงถึงวิธีการสร้างวัตถุหลักดังแสดงในตัวอย่างต่อไปนี้:
<script type="text/javascript">// ตัวสร้างหลัก
ฟังก์ชั่นบุคคล () {
this.name = "trigkit4";
-
// เพิ่มลงในแอตทริบิวต์ต้นแบบ
person.prototype.getName = function () {
ส่งคืนสิ่งนี้ชื่อ;
-
// สร้างวัตถุคลาสบุคคลใหม่
var obj = คนใหม่ ();
// สืบทอด
var kid = object (person.prototype);
console.log (typeof kid.getName); // ฟังก์ชั่นเพราะมันอยู่ในต้นแบบ
console.log (typeof kid.name); // undefined เพราะเฉพาะต้นแบบนี้ได้รับการสืบทอด
</script>