1. วัตถุ prototype
1.1 ข้อเสียของตัวสร้าง
JavaScript สร้างวัตถุใหม่ผ่านตัวสร้างดังนั้นตัวสร้างจึงถือเป็นเทมเพลตสำหรับวัตถุ คุณสมบัติและวิธีการของวัตถุอินสแตนซ์สามารถกำหนดได้ภายในตัวสร้าง
ฟังก์ชัน cat (ชื่อ, สี) {this.name = name; this.color = color;} var cat1 = แมวใหม่ ('ผมใหญ่', 'ขาว'); cat1.name // 'big hair'cat1.color //' White 'ฟังก์ชั่น CAT ในรหัสด้านบนเป็นตัวสร้าง แอตทริบิวต์ชื่อและแอตทริบิวต์สีถูกกำหนดภายใน วัตถุอินสแตนซ์ทั้งหมดจะสร้างแอตทริบิวต์ทั้งสองนี้ อย่างไรก็ตามการทำเช่นนั้นเป็นการสูญเสียทรัพยากรของระบบเนื่องจากคุณสมบัติไม่สามารถแบ่งปันได้ระหว่างอินสแตนซ์วัตถุของตัวสร้างเดียวกัน
ฟังก์ชัน cat (ชื่อ, สี) {this.name = name; this.color = color; this.meow = function () {console.log ('mew, mew, mew ... '); };} var cat1 = แมวใหม่ ('ผมตัวใหญ่', 'ขาว'); var cat2 = แมวใหม่ ('ei mao', 'ดำ'); cat1.meow === cat2.meow // falseในรหัสข้างต้น CAT1 และ CAT2 เป็นอินสแตนซ์ของตัวสร้างเดียวกัน อย่างไรก็ตามวิธีการ meow ของพวกเขาแตกต่างกันนั่นคือทุกครั้งที่มีการสร้างอินสแตนซ์ใหม่จะมีการสร้างวิธีการใหม่ของ Meow นี่ไม่ใช่ทรัพยากรของระบบที่จำเป็นและไม่ต้องเสียเพราะวิธีการ MEOW ทั้งหมดเป็นพฤติกรรมเดียวกันและควรแบ่งปันอย่างสมบูรณ์
1.2 บทบาทของคุณลักษณะต้นแบบ
ในภาษา JavaScript แต่ละวัตถุมีวัตถุต้นแบบที่สอดคล้องกันเรียกว่าวัตถุต้นแบบ คุณสมบัติและวิธีการทั้งหมดที่กำหนดไว้ในวัตถุต้นแบบสามารถสืบทอดได้โดยวัตถุที่ได้รับ นี่คือการออกแบบพื้นฐานของกลไกการสืบทอด JavaScript
นอกเหนือจากวิธีการนี้ JavaScript ยังให้อีกวิธีหนึ่งในการกำหนดวัตถุอินสแตนซ์ เรารู้ว่าตัวสร้างเป็นฟังก์ชั่นวัตถุและยังมีคุณสมบัติและวิธีการของตัวเอง หนึ่งแอตทริบิวต์ต้นแบบชี้ไปที่วัตถุอื่นซึ่งโดยทั่วไปเรียกว่าวัตถุต้นแบบ วัตถุนี้พิเศษมาก ตราบใดที่คุณสมบัติและวิธีการที่กำหนดไว้สามารถแชร์ได้โดยวัตถุอินสแตนซ์ทั้งหมด กล่าวคือเมื่อตัวสร้างสร้างวัตถุอินสแตนซ์แอตทริบิวต์ต้นแบบจะถูกกำหนดให้กับวัตถุอินสแตนซ์โดยอัตโนมัติ
ฟังก์ชันสัตว์ (ชื่อ) {this.name = name;} iment.prototype.color = "White"; var cat1 = สัตว์ใหม่ ('ผมตัวใหญ่'); var cat2 = สัตว์ใหม่ ('erimao'); cat1.color // 'White'cat2.color //' White 'รหัสด้านบนเพิ่มแอตทริบิวต์สีให้กับวัตถุต้นแบบของสัตว์สร้าง เป็นผลให้วัตถุอินสแตนซ์ทั้งสอง cat1 และ cat2 มีคุณสมบัตินี้
โดยเฉพาะอย่างยิ่งตราบใดที่วัตถุต้นแบบได้รับการแก้ไขการเปลี่ยนแปลงจะถูกสะท้อนทันทีในวัตถุอินสแตนซ์
Animal.prototype.color = "Yellow"; cat1.color // 'Yellow'cat2.color //' Yellow '
รหัสด้านบนจะเปลี่ยนค่าของแอตทริบิวต์สีของวัตถุต้นแบบเป็นสีเหลืองและค่าของแอตทริบิวต์สีของวัตถุอินสแตนซ์ทั้งสองจะเปลี่ยนทันที นี่เป็นเพราะวัตถุอินสแตนซ์ไม่มีแอตทริบิวต์สีและพวกเขาทั้งหมดอ่านแอตทริบิวต์สีของวัตถุต้นแบบ กล่าวคือเมื่อวัตถุอินสแตนซ์เองไม่มีคุณสมบัติหรือวิธีการบางอย่างมันจะไปที่วัตถุต้นแบบของตัวสร้างเพื่อค้นหาคุณสมบัติหรือวิธีการ นี่คือสิ่งพิเศษเกี่ยวกับวัตถุต้นแบบ
หากวัตถุอินสแตนซ์เองมีคุณสมบัติหรือวิธีการบางอย่างมันจะไม่ค้นหาคุณสมบัติหรือวิธีนี้ในวัตถุต้นแบบอีกต่อไป
cat1.color = 'black'; cat2.color // 'yellow'animal.prototype.color // "สีเหลือง";
รหัสด้านบนจะเปลี่ยนคุณสมบัติสีของวัตถุอินสแตนซ์ cat1 เป็นสีดำเพื่อไม่ให้อ่านคุณสมบัติสีจากวัตถุต้นแบบอีกต่อไปและค่าของหลังยังคงเป็นสีเหลือง
ในระยะสั้นฟังก์ชั่นของวัตถุต้นแบบคือการกำหนดคุณสมบัติและวิธีการที่ใช้ร่วมกันโดยวัตถุอินสแตนซ์ทั้งหมดดังนั้นจึงเรียกว่าต้นแบบของวัตถุอินสแตนซ์และวัตถุอินสแตนซ์สามารถถือได้ว่าได้มาจากวัตถุต้นแบบ
Animal.prototype.walk = function () {console.log (this.name + 'กำลังเดินอยู่');};รหัสด้านบนกำหนดวิธีการเดินบนวัตถุสัตว์ protype ซึ่งจะถูกเรียกใช้วัตถุอินสแตนซ์สัตว์ทั้งหมด
1.3 ห่วงโซ่ต้นแบบ
เนื่องจากวัตถุทั้งหมดใน JavaScript มีตัวสร้างและตัวสร้างทั้งหมดมีคุณลักษณะต้นแบบ (จริง ๆ แล้วฟังก์ชั่นทั้งหมดมีคุณลักษณะต้นแบบ) วัตถุทั้งหมดมีวัตถุต้นแบบต้นแบบของตัวเอง
ดังนั้นคุณสมบัติและวิธีการของวัตถุอาจถูกกำหนดไว้ในตัวเองหรือบนวัตถุต้นแบบ (เช่นวิธีการเดินในรหัสข้างต้น) เนื่องจากต้นแบบนั้นเป็นวัตถุและมีต้นแบบของตัวเองจึงเกิดห่วงโซ่ต้นแบบ ตัวอย่างเช่น Object A คือต้นแบบของวัตถุ B, Object B คือต้นแบบของวัตถุ C และอื่น ๆ เนื่องจากการติดตามรูทของแหล่งที่มาวัตถุที่แหล่งกำเนิดจะถูกสร้างขึ้นจากตัวสร้างวัตถุ (โดยใช้คำสั่ง Object () ใหม่) ดังนั้นหากคุณติดตามมันขึ้นเลเยอร์โดยเลเยอร์ ดังนั้นมีต้นแบบสำหรับ Object.prototype หรือไม่? คำตอบอาจเป็นใช่หรือไม่ใช่เพราะต้นแบบของ Object.prototype เป็นโมฆะโดยไม่มีคุณสมบัติและวิธีการใด ๆ
Object.getPrototypeof (object.prototype) // null
รหัสข้างต้นระบุว่าต้นแบบของวัตถุวัตถุโปรโตไทป์เป็นโมฆะ เนื่องจาก NULL ไม่มีคุณสมบัติโซ่ต้นแบบจึงสิ้นสุดที่นี่
ฟังก์ชั่นของ "chain prototype chain" คือเมื่ออ่านแอตทริบิวต์บางอย่างของวัตถุเครื่องยนต์ JavaScript แรกจะค้นหาคุณลักษณะของวัตถุเอง หากไม่สามารถพบได้มันจะมองหาต้นแบบ หากยังไม่สามารถพบได้มันจะมองหาต้นแบบของต้นแบบ และอื่น ๆ หาก Object.prototype ที่ระดับบนสุดยังไม่พบมันจะกลับมาที่ไม่ได้กำหนด
ตัวอย่างเช่นหากแอตทริบิวต์ต้นแบบของฟังก์ชั่นชี้ไปที่อาร์เรย์นั่นหมายความว่าฟังก์ชันสามารถใช้เป็นตัวสร้างอาร์เรย์ได้เนื่องจากวัตถุอินสแตนซ์ที่สร้างขึ้นสามารถเรียกใช้วิธีอาร์เรย์ผ่านแอตทริบิวต์ต้นแบบ
ฟังก์ชั่น myarray () {} myarray.prototype = new Array (); myarray.prototype.constructor = myarray; var mine = new myarray (); mine.push (1, 2, 3);เหมืองในรหัสด้านบนเป็นวัตถุอินสแตนซ์ของ MyArray เนื่องจากคุณสมบัติต้นแบบของ MyArray ชี้ไปที่อาร์เรย์ของฉันจึงสามารถเรียกใช้วิธีการอาร์เรย์ (วิธีการเหล่านี้ถูกกำหนดไว้ในวัตถุต้นแบบของอาร์เรย์) สำหรับบรรทัดสุดท้ายของการแสดงออกอินสแตนซ์ของเรารู้ว่าตัวดำเนินการอินสแตนซ์ของตัวดำเนินการเพื่อเปรียบเทียบว่าวัตถุเป็นอินสแตนซ์ของตัวสร้างและบรรทัดสุดท้ายระบุว่าเหมืองเป็นอินสแตนซ์ของอาร์เรย์
อินสแตนซ์ของฉันของอาร์เรย์ // เทียบเท่ากับ (array === myarray.prototype.constructor) || (array === array.prototype.constructor) || (array === object.prototype.constructor)
รหัสด้านบนแสดงให้เห็นถึงสาระสำคัญของตัวดำเนินการอินสแตนซ์ของตัวดำเนินการซึ่งเปรียบเทียบกับแอตทริบิวต์ตัวสร้างของวัตถุต้นแบบทั้งหมดของวัตถุอินสแตนซ์ (สำหรับการแนะนำของแอตทริบิวต์นี้โปรดดูส่วนถัดไป) ตราบใดที่มีหนึ่งมันจะกลับมาเป็นจริงมิฉะนั้นมันจะกลับมาเป็นเท็จ
1.4 แอตทริบิวต์ตัวสร้าง
วัตถุต้นแบบมีแอตทริบิวต์ตัวสร้างที่ชี้ไปที่ฟังก์ชั่นคอนสตรัคเตอร์ที่วัตถุต้นแบบตั้งอยู่ตามค่าเริ่มต้น
ฟังก์ชั่น p () {} p.prototype.constructor === p // trueเนื่องจากแอตทริบิวต์ตัวสร้างถูกกำหนดไว้ในวัตถุต้นแบบจึงหมายความว่าสามารถสืบทอดได้โดยวัตถุอินสแตนซ์ทั้งหมด
ฟังก์ชั่น p () {} var p = ใหม่ p (); p.constructor // ฟังก์ชั่น p () {} p.constructor === p.prototype.constructor // truep.hasownproperty ('constructor') // falseรหัสข้างต้นระบุว่า P เป็นวัตถุอินสแตนซ์ของตัวสร้าง P แต่ P ตัวเองไม่มีแอตทริบิวต์ตัวสร้างซึ่งจริง ๆ แล้วอ่านแอตทริบิวต์ P.Prototype.Constructor บนห่วงโซ่ต้นแบบ
ฟังก์ชั่นของแอตทริบิวต์ตัวสร้างคือการแยกแยะว่าตัวสร้างวัตถุต้นแบบถูกกำหนดไว้
ฟังก์ชั่น f () {}; var f = new f (); f.constructor === f // truef.constructor === regexp // falseรหัสข้างต้นหมายความว่าการใช้คุณสมบัติตัวสร้างจะถูกกำหนดว่าฟังก์ชันตัวสร้างของตัวแปร F คือ F ไม่ใช่ regexp
2.Object.getPrototypeof Method
Method.get.getPrototypeof ส่งคืนต้นแบบของวัตถุ
// ต้นแบบของวัตถุเปล่าคือ Object.prototypeobject.getPrototypeof ({}) === Object.prototype // true // prototype ของฟังก์ชันคือฟังก์ชัน prototypefunction f () f // จากนั้นต้นแบบของ f คือ f.prototypevar f = new f (); object.getPrototypeof (f) === f.prototype // true3.Object.create Method
วิธีการสร้างวัตถุใช้เพื่อสร้างวัตถุใหม่และสามารถแทนที่คำสั่งใหม่ มันยอมรับวัตถุเป็นอาร์กิวเมนต์และส่งคืนวัตถุใหม่ซึ่งสืบทอดคุณสมบัติของอดีตอย่างสมบูรณ์นั่นคืออดีตกลายเป็นต้นแบบของหลัง
var o1 = {p: 1}; var o2 = object.create (o1); o2.p // 1ในรหัสข้างต้นวิธีการสร้างวัตถุสร้าง O2 ตาม O1 ในเวลานี้ O1 กลายเป็นต้นแบบของ O2 นั่นคือ O2 สืบทอดคุณสมบัติทั้งหมดของ O1
วิธีการสร้าง object.create นั้นเทียบเท่ากับรหัสต่อไปนี้ หากเบราว์เซอร์เก่าไม่รองรับวิธีการสร้างวัตถุคุณสามารถใช้รหัสต่อไปนี้เพื่อปรับใช้ด้วยตัวเอง
if (typeof object.create! == "function") {object.create = function (o) {function f () {} f.prototype = o; คืน F () ใหม่; -รหัสข้างต้นแสดงให้เห็นว่าวิธีการสร้างวัตถุนั้นกำลังสร้างตัวสร้างใหม่ F จากนั้นอนุญาตให้แอตทริบิวต์ต้นแบบของ F ชี้ไปที่วัตถุ O เป็นต้นแบบและในที่สุดก็ส่งคืนอินสแตนซ์ของ F เพื่อให้อินสแตนซ์สามารถสืบทอดแอตทริบิวต์ของ O
วัตถุใหม่ที่สร้างขึ้นในสามวิธีต่อไปนี้เทียบเท่า
var o1 = object.create ({}); var o2 = object.create (object.prototype); var o3 = วัตถุใหม่ ();หากคุณต้องการสร้างวัตถุที่ไม่ได้สืบทอดคุณสมบัติใด ๆ (เช่น ToString และ Valueof Methods) คุณสามารถตั้งค่าพารามิเตอร์ object.create เป็น null
var o = object.create (null); o.valueof () // typeError: Object [Object Object] ไม่มีวิธี 'valueof'
รหัสข้างต้นระบุว่าหากต้นแบบของวัตถุ O เป็นโมฆะมันไม่มีคุณสมบัติบางอย่างที่กำหนดไว้ในวัตถุวัตถุ prototype เช่นวิธีการ valueof
เมื่อใช้วิธีการสร้างวัตถุจะต้องมีการจัดเตรียมต้นแบบวัตถุมิฉะนั้นจะมีการรายงานข้อผิดพลาด
Object.create () // typeerror: วัตถุต้นแบบอาจเป็นวัตถุหรือ null เท่านั้น
วัตถุใหม่ที่สร้างโดย Object.create Method จะสืบทอดต้นแบบแบบไดนามิก การเพิ่มหรือแก้ไขวิธีการใด ๆ บนต้นแบบจะสะท้อนถึงวัตถุใหม่ทันที
var o1 = {p: 1}; var o2 = object.create (o1); o1.p = 2; o2.p // 2;รหัสข้างต้นระบุว่าการแก้ไขต้นแบบวัตถุจะส่งผลกระทบต่อวัตถุที่สร้างขึ้นใหม่
นอกเหนือจากต้นแบบวัตถุวิธีการสร้างวัตถุยังสามารถยอมรับพารามิเตอร์ที่สองซึ่งเป็นตัวแทนของแอตทริบิวต์วัตถุที่อธิบายแอตทริบิวต์ซึ่งเป็นรูปแบบเดียวกับ Object.defineProperties ที่ใช้ คุณสมบัติของวัตถุที่อธิบายจะถูกเพิ่มลงในวัตถุใหม่
var o = object.create (object.prototype, {p1: {value: 123, enumerable: true}, p2: {value: "abc", enumerable: true}}); o.p1 // 123o.p2 // "abc"เนื่องจากวิธีการสร้างวัตถุไม่ได้ใช้ตัวสร้างตัวดำเนินการอินสแตนซ์ของตัวดำเนินการไม่สามารถใช้เพื่อกำหนดว่าอินสแตนซ์ของตัวสร้างวัตถุใด ในเวลานี้คุณสามารถใช้วิธี isprototypeof ต่อไปนี้เพื่อตีความวัตถุต้นแบบที่เป็น
4. วิธีการ
วิธี isprototypeof ใช้เพื่อตรวจสอบว่าวัตถุเป็นต้นแบบของวัตถุอื่นหรือไม่
var o1 = {}; var o2 = object.create (o1); var o3 = object.create (o2); o2.isprototypeof (O3) // trueo1.isprototypeof (O3) // trueรหัสด้านบนแสดงให้เห็นว่า isprotepeof ส่งคืนจริงตราบใดที่วัตถุอยู่ในห่วงโซ่ต้นแบบ
5. ตัวอย่างง่ายๆ
var classdemo = function () {// ตัวแปรส่วนตัวคงที่ var private_static_var = 'aaaa'; // วิธีการส่วนตัวแบบคงที่ var private_static_func = ฟังก์ชั่น (คีย์) {return key + private_static_var; } // วิธีการส่วนตัวคีย์คือการผ่าน var private_func = ฟังก์ชั่นนี้ (self, key) {return private_static_func (key + self.id); } var _class = function (id) {// constructor this.id = id; // ตัวแปรสาธารณะ} // public method_class.prototype.public_func = ฟังก์ชั่น (คีย์) {return private_func (นี่, คีย์); } return _class;} (); var a = new classdemo ('Hello World'); Alert (A.Public_Func ('World Hello'));ไม่มีวิธีง่ายๆในการใช้ตัวแปรส่วนตัวและตัวแปร/วิธีการคงที่สาธารณะ แต่การห่อหุ้มก็เพียงพอที่จะทำในระดับนี้