ก่อนอื่นให้แบ่งปันตัวอย่างของการสืบทอด JS Prototype สำหรับการอ้างอิงของคุณ เนื้อหาเฉพาะมีดังนี้
1. JS ต้นแบบการสืบทอด
<! doctype html> <html> <head> <meta charset = "utf-8"> <title> js ต้นแบบการสืบทอด </title> </head> <body> <! - // ประโยคนี้เป็นแกนหลักของการสืบทอดต้นแบบ วัตถุต้นแบบของฟังก์ชั่นคือ Object literal_f.prototype = OBJ; ส่งคืน _f ใหม่; } // ประกาศวัตถุตัวอักษรตัวอักษรตัวแรก var Animal = {somthing: 'Apple', Eat: function () {console.log ("กิน" + this.somthing); }} // ไม่จำเป็นต้องกำหนดคลาสย่อยของบุคคลเพียงแค่ทำการโคลน var cat = โคลน (สัตว์); // คุณสามารถรับค่าเริ่มต้นโดยตรงโดยบุคคลหรือคุณสามารถเพิ่มหรือแก้ไขแอตทริบิวต์และวิธีการ console.log (cat.eat ()); cat.somthing = 'สีส้ม'; console.log (cat.eat ()); // ประกาศ subclass และดำเนินการโคลน var ใครบางคน = โคลน (แมว); </script> </body> </html>2. หลักการทำงานของการสืบทอดต้นแบบ JavaScript
เป็นที่ทราบกันดีว่า JavaScript ใช้มรดกต้นแบบ แต่เนื่องจากมีเพียงตัวอย่างเดียวของการใช้งานผู้ให้บริการใหม่โดยค่าเริ่มต้นคำอธิบายของมันทำให้เกิดความสับสนเสมอ มาอธิบายว่าการสืบทอดต้นแบบคืออะไรและวิธีการใช้การสืบทอดต้นแบบใน JavaScript
คำจำกัดความของการสืบทอดต้นแบบ
เมื่อคุณอ่านคำอธิบายเกี่ยวกับการสืบทอด JS Prototype คุณมักจะเห็นข้อความต่อไปนี้:
เมื่อมองหาคุณสมบัติของวัตถุ JavaScript จะสำรวจห่วงโซ่ต้นแบบขึ้นไปจนกว่าจะพบแอตทริบิวต์ของชื่อที่กำหนด - จาก Secret Garden of JavaScript
การใช้งาน JavaScript ส่วนใหญ่ใช้แอตทริบิวต์ __proto__ เพื่อแสดงถึงห่วงโซ่ต้นแบบของวัตถุ ในบทความนี้เราจะเห็นความแตกต่างระหว่าง __proto__ และต้นแบบ
หมายเหตุ: __proto__ เป็นการใช้งานอย่างไม่เป็นทางการที่ไม่ควรปรากฏในรหัสของคุณ ที่นี่เราเพิ่งใช้มันเพื่ออธิบายวิธีการสืบทอดการสืบทอดของ JavaScript Prototype
รหัสต่อไปนี้แสดงให้เห็นว่าเครื่องยนต์ JS ค้นหาคุณสมบัติอย่างไร:
ฟังก์ชั่น getProperty (obj, prop) {ถ้า (obj.hasownproperty (prop)) ส่งคืน obj [prop] อื่น ๆ ถ้า (obj .__ proto__! == null) return getProperty (obj .__ proto__, prop) อื่น ๆลองยกตัวอย่างร่วมกัน: จุดสองมิติมีพิกัดสองมิติ XY ซึ่งคล้ายกับการพิมพ์
การใช้คำจำกัดความของการสืบทอดต้นแบบที่เรากล่าวถึงก่อนหน้านี้เราสร้างจุดวัตถุที่มีคุณสมบัติสามประการ: X, Y และ PRINT ในการสร้างจุดสองมิติใหม่เราจำเป็นต้องสร้างวัตถุใหม่เพื่อให้จุดแอตทริบิวต์ __proto__ เป็นจุด:
var point = {x: 0, y: 0, print: function () {console.log (this.x, this.y); - var p = {x: 10, y: 20, __proto__: จุด}; p.print (); // 10 20JavaScript Weird Prototype การสืบทอด
สิ่งที่ทำให้สับสนคือไม่มีใครที่สอนมรดกต้นแบบจะให้รหัสชิ้นส่วนดังกล่าว แต่จะให้รหัสต่อไปนี้:
จุดฟังก์ชัน (x, y) {this.x = x; this.y = y; } point.prototype = {print: function () {console.log (this.x, this.y); - var p = จุดใหม่ (10, 20); p.print (); // 10 20สิ่งนี้แตกต่างจากสิ่งที่ฉันพูด จุดที่นี่กลายเป็นฟังก์ชั่นและยังมีแอตทริบิวต์ต้นแบบและมีตัวดำเนินการใหม่ เกิดอะไรขึ้นกับสิ่งนี้?
ผู้ให้บริการใหม่ทำงานอย่างไร
ผู้สร้าง Brendan Eich ต้องการสร้าง JS ไม่แตกต่างจากภาษาการเขียนโปรแกรมเชิงวัตถุแบบดั้งเดิมมากเช่น Java และ C ++ ในภาษาเหล่านี้เราใช้ตัวดำเนินการใหม่เพื่อยกตัวอย่างวัตถุใหม่ไปยังชั้นเรียน ดังนั้นเขาจึงเขียนผู้ให้บริการรายใหม่ใน JS
มีแนวคิดคอนสตรัคเตอร์ใน C ++ สำหรับการเริ่มต้นคุณสมบัติอินสแตนซ์ดังนั้นผู้ให้บริการใหม่จะต้องกำหนดเป้าหมายที่ฟังก์ชั่น
เราต้องใส่วิธีการวัตถุในที่เดียว เนื่องจากเราใช้ภาษาต้นแบบเราจะนำมันลงในคุณสมบัติต้นแบบของฟังก์ชั่น
ตัวดำเนินการใหม่ยอมรับฟังก์ชั่น F และพารามิเตอร์: F F (อาร์กิวเมนต์ใหม่ ... ) กระบวนการนี้แบ่งออกเป็นสามขั้นตอน:
สร้างอินสแตนซ์ของคลาส ขั้นตอนนี้คือการตั้งค่าคุณสมบัติ __proto__ ของวัตถุเปล่าเป็น f.prototype
เริ่มต้นอินสแตนซ์ ฟังก์ชั่น F ถูกส่งผ่านในพารามิเตอร์และเรียกและคำหลักนี้ถูกตั้งค่าเป็นอินสแตนซ์นี้
ส่งคืนอินสแตนซ์
ตอนนี้เรารู้ว่างานใหม่เราสามารถนำไปใช้ในรหัส JS:
ฟังก์ชั่นใหม่ (f) {var n = {'__proto__': f.prototype}; /*ขั้นตอนที่ 1*/ return function () {f.apply (n, อาร์กิวเมนต์); /*ขั้นตอนที่ 2*/ return n; /*ขั้นตอนที่ 3*/}; -ตัวอย่างเล็ก ๆ ของสถานการณ์การทำงานของเขา:
จุดฟังก์ชัน (x, y) {this.x = x; this.y = y; } point.prototype = {print: function () {console.log (this.x, this.y); - var p1 = จุดใหม่ (10, 20); p1.print (); // 10 20 console.log (จุดอินสแตนซ์ p1); // true var p2 = new (จุด) (10, 20); p2.print (); // 10 20 console.log (จุดอินสแตนซ์ p2); // จริงมรดกต้นแบบที่แท้จริงใน JavaScript
ข้อกำหนด ECMA ของ JS ช่วยให้เราสามารถใช้ตัวดำเนินการใหม่สำหรับการสืบทอดต้นแบบ แต่นายดักลาสคร็อคฟอร์ดผู้ยิ่งใหญ่ค้นพบวิธีที่จะใช้ใหม่เพื่อให้ได้มรดกต้นแบบที่แท้จริง! เขาเขียนฟังก์ชั่นวัตถุสร้างขึ้นดังนี้:
Object.create = function (parent) {function f () {} f.prototype = parent; คืน F () ใหม่; -สิ่งนี้ดูแปลก ๆ แต่มันค่อนข้างกระชับ: มันสร้างวัตถุใหม่และต้นแบบให้กับค่าใด ๆ ที่คุณต้องการตั้งค่า หากเราอนุญาต __proto__ เราสามารถเขียนสิ่งนี้:
Object.create = function (parent) {return {'__proto__': parent}; -รหัสต่อไปนี้ช่วยให้จุดของเราสามารถนำมรดกต้นแบบจริงมาใช้:
var point = {x: 0, y: 0, print: function () {console.log (this.x, this.y); - var p = object.create (จุด); px = 10; PY = 20; p.print (); // 10 20สรุปแล้ว
เราได้เรียนรู้ว่าการสืบทอดของ JS Prototype คืออะไรและวิธีที่ JS สามารถนำไปใช้ในวิธีที่เฉพาะเจาะจง อย่างไรก็ตามการใช้มรดกต้นแบบจริง (เช่น Object.create และ __proto__) ยังคงมีข้อเสียดังต่อไปนี้:
การขาดมาตรฐาน: __ proto__ ไม่ใช่การใช้มาตรฐานหรือแม้แต่การใช้งานไม่อนุมัติ ในเวลาเดียวกันวัตถุต้นฉบับสร้างและเวอร์ชันดั้งเดิมที่เขียนโดย Daoye ก็แตกต่างกันเช่นกัน
การเพิ่มประสิทธิภาพที่ไม่ดี: ไม่ว่าจะเป็นวัตถุพื้นเมืองหรือที่กำหนดเองสร้างประสิทธิภาพการทำงานของมันน้อยกว่าของใหม่และอดีตช้ากว่า 10 เท่าช้ากว่า 10 เท่า
ข้างต้นเป็นเรื่องเกี่ยวกับบทความนี้ฉันหวังว่ามันจะเป็นประโยชน์กับการเรียนรู้ของทุกคน