ในภาษาที่มุ่งเน้นวัตถุทั่วไปเช่น Java มีแนวคิดของชั้นเรียน คลาสคือเทมเพลตของวัตถุและวัตถุเป็นอินสแตนซ์ของคลาส อย่างไรก็ตามในระบบภาษา JavaScript ไม่มีแนวคิดของชั้นเรียน JavaScript ไม่ได้ขึ้นอยู่กับ 'คลาส' แต่ถูกนำไปใช้ผ่านตัวสร้างและเครือข่ายต้นแบบ อย่างไรก็ตาม ES6 มีวิธีการเขียนที่ใกล้เคียงกับภาษาดั้งเดิมแนะนำแนวคิดของคลาส (คลาส) เป็นเทมเพลตวัตถุ ผ่านคำหลักของคลาสคุณสามารถกำหนดคลาส โดยทั่วไปชั้นเรียนของ ES6 ถือได้ว่าเป็นเพียงน้ำตาลไวยากรณ์ ฟังก์ชั่นส่วนใหญ่สามารถทำได้โดย ES5 วิธีการเขียนคลาสใหม่ทำให้วัตถุต้นแบบเขียนชัดเจนขึ้นและคล้ายกับไวยากรณ์การเขียนโปรแกรมเชิงวัตถุ
ตามนิสัยของฉันฉันจะให้ไดเรกทอรีบทความก่อนเขียน
เนื้อหาต่อไปนี้จะถูกแบ่งออกเป็นส่วนย่อยต่อไปนี้:
1. การแนะนำสั้น ๆ เกี่ยวกับผู้สร้าง
2. ข้อเสียของตัวสร้าง
3. บทบาทของคุณลักษณะต้นแบบ
4. ห่วงโซ่ต้นแบบ
5. แอตทริบิวต์ของตัวสร้าง
5.1: บทบาทของแอตทริบิวต์ตัวสร้าง
6. อินสแตนซ์ของตัวดำเนินการ
1. การแนะนำสั้น ๆ เกี่ยวกับผู้สร้าง
ในบทความของฉันเกี่ยวกับความสัมพันธ์ที่ใกล้ชิดระหว่างตัวสร้างและคำสั่งใหม่ใน JavaScript แนวคิดและลักษณะของตัวสร้างหลักการและการใช้คำสั่งใหม่ ฯลฯ ได้รับการแนะนำในรายละเอียด หากคุณไม่คุ้นเคยกับตัวสร้างคุณสามารถไปและลิ้มรสพวกเขาอย่างระมัดระวัง นี่คือรีวิวง่ายๆ
ตัวสร้างที่เรียกว่าเป็นฟังก์ชั่นที่ให้แม่แบบสำหรับการสร้างวัตถุและอธิบายโครงสร้างพื้นฐานของวัตถุ ตัวสร้างสามารถสร้างวัตถุหลายชิ้นแต่ละชิ้นมีโครงสร้างเดียวกัน โดยทั่วไปตัวสร้างเป็นเทมเพลตสำหรับวัตถุและวัตถุเป็นอินสแตนซ์ของตัวสร้าง
ลักษณะของตัวสร้างคือ:
ตอบ: ตัวอักษรตัวแรกของชื่อฟังก์ชั่นของตัวสร้างจะต้องเป็นตัวพิมพ์ใหญ่
B: ใช้วัตถุนี้ภายในเพื่อชี้ไปที่อินสแตนซ์ของวัตถุที่จะสร้าง
C: ใช้ตัวดำเนินการใหม่เพื่อเรียกตัวสร้างและส่งคืนอินสแตนซ์ของวัตถุ
มาดูตัวอย่างที่ง่ายที่สุด
ฟังก์ชันบุคคล () {this.name = 'keith';} var boy = บุคคลใหม่ (); console.log (boy.name); // 'Keith'2. ข้อเสียของตัวสร้าง
วัตถุอินสแตนซ์ทั้งหมดสามารถสืบทอดคุณสมบัติและวิธีการในตัวสร้าง อย่างไรก็ตามคุณสมบัติไม่สามารถแชร์ระหว่างอินสแตนซ์ของวัตถุเดียวกัน
ฟังก์ชันบุคคล (ชื่อ, ความสูง) {this.name = name; this.height = ความสูง; this.hobby = function () {return 'ดูภาพยนตร์';}} var boy = บุคคลใหม่ ('keith', 180); var girl = คนใหม่ ('rascal', 153); console.log (boy.name); // 'keith' console.log (girl.name); // 'rascal' console.log (boy.hobby === girl.hobby); //เท็จในรหัสข้างต้นบุคคลที่สร้างขึ้นสร้างวัตถุสองอินสแตนซ์เด็กและเด็กหญิงและมีคุณสมบัติสองอย่างและวิธีการ อย่างไรก็ตามวิธีงานอดิเรกของพวกเขาแตกต่างกัน กล่าวคือเมื่อใดก็ตามที่คุณใช้ใหม่เพื่อเรียกตัวสร้างเพื่อนำมันกลับมาเป็นอินสแตนซ์ของวัตถุจะมีการสร้างวิธีงานอดิเรก สิ่งนี้ไม่จำเป็นหรือไม่ต้องเสียทรัพยากรเพราะวิธีการงานอดิเรกทั้งหมดเป็นพฤติกรรมเด็กและสามารถแบ่งปันได้อย่างสมบูรณ์โดยสองอินสแตนซ์วัตถุ
ดังนั้นข้อเสียของตัวสร้างคือคุณสมบัติหรือวิธีการไม่สามารถใช้ร่วมกันระหว่างอินสแตนซ์วัตถุของตัวสร้างเดียวกัน
3. บทบาทของคุณลักษณะต้นแบบ
เพื่อแก้ปัญหาข้อเสียของการไม่สามารถแบ่งปันคุณสมบัติระหว่างอินสแตนซ์วัตถุของตัวสร้าง JS ให้คุณลักษณะต้นแบบ
แต่ละประเภทข้อมูลใน JS เป็นวัตถุ (ยกเว้น null และ undefined) และแต่ละวัตถุสืบทอดมาจากวัตถุอื่นส่วนหลังเรียกว่าวัตถุ "ต้นแบบ" ยกเว้น null ซึ่งไม่มีวัตถุต้นแบบของตัวเอง
คุณสมบัติและวิธีการทั้งหมดในวัตถุต้นแบบจะถูกแชร์โดยอินสแตนซ์ของวัตถุ
เมื่ออินสแตนซ์ของวัตถุถูกสร้างขึ้นผ่านตัวสร้างต้นแบบของอินสแตนซ์ของวัตถุจะถูกชี้ไปที่คุณสมบัติต้นแบบของตัวสร้าง ตัวสร้างแต่ละตัวมีแอตทริบิวต์ต้นแบบซึ่งเป็นวัตถุต้นแบบของอินสแตนซ์วัตถุ
ฟังก์ชันบุคคล (ชื่อ, ความสูง) {this.name = name; this.height = ความสูง; } person.prototype.hobby = function () {return 'ดูภาพยนตร์'; } var boy = คนใหม่ ('keith', 180); var girl = คนใหม่ ('rascal', 153); console.log (boy.name); // 'keith' console.log (girl.name); // 'rascal' console.log (boy.hobby === girl.hobby); //จริงในรหัสข้างต้นหากวิธีการงานอดิเรกถูกวางไว้บนวัตถุต้นแบบแล้ววัตถุอินสแตนซ์ทั้งสองจะใช้วิธีเดียวกัน ฉันหวังว่าทุกคนจะเข้าใจว่าสำหรับตัวสร้างต้นแบบเป็นคุณสมบัติเป็นตัวสร้าง สำหรับอินสแตนซ์วัตถุต้นแบบเป็นวัตถุต้นแบบของอินสแตนซ์วัตถุ ดังนั้นต้นแบบจึงเป็นคุณสมบัติและวัตถุ
วัตถุต้นแบบไม่ใช่คุณสมบัติของอินสแตนซ์วัตถุ แอตทริบิวต์ของอินสแตนซ์ของวัตถุเป็นแอตทริบิวต์ที่สืบทอดมาจากคำจำกัดความของตัวสร้างเนื่องจากมีคำหลักภายในตัวสร้างเพื่อชี้ไปที่อินสแตนซ์ของวัตถุที่จะสร้าง คุณสมบัติของอินสแตนซ์ของวัตถุเป็นแอตทริบิวต์ที่กำหนดภายในโดยตัวสร้าง ตราบใดที่คุณสมบัติและวิธีการบนวัตถุต้นแบบได้รับการแก้ไขการเปลี่ยนแปลงจะถูกสะท้อนทันทีในทุกอินสแตนซ์ของวัตถุ
person.prototype.hobby = function () {return 'swimming'; } console.log (boy.hobby === girl.hobby); // true console.log (boy.hobby ()); // 'swimming'console.log (girl.hobby ()); //'การว่ายน้ำ'ในรหัสข้างต้นหลังจากแก้ไขวิธีงานอดิเรกของวัตถุต้นแบบแล้วอินสแตนซ์ของวัตถุทั้งสองมีการเปลี่ยนแปลง นี่เป็นเพราะอินสแตนซ์ของวัตถุไม่มีวิธีการงานอดิเรกพวกเขาเป็นวิธีงานอดิเรกทั้งหมดที่อ่านวัตถุต้นแบบ กล่าวคือเมื่ออินสแตนซ์ของวัตถุไม่มีคุณสมบัติและวิธีการมันจะค้นหาบนวัตถุต้นแบบ หากวัตถุอินสแตนซ์เองมีคุณสมบัติหรือวิธีการบางอย่างมันจะไม่ถูกค้นหาบนวัตถุต้นแบบ
boy.hobby = function () {return 'เล่นบาสเก็ตบอล'; } console.log (boy.hobby ()); // 'เล่นบาสเก็ตบอล' console.log (girl.hobby ()); //'การว่ายน้ำ'ในรหัสข้างต้นเมื่อวิธีการงานอดิเรกของอินสแตนซ์วัตถุบอยได้รับการแก้ไขวิธีงานอดิเรกบนวัตถุต้นแบบจะไม่ได้รับการสืบทอด อย่างไรก็ตามหญิงสาวจะยังคงสืบทอดวิธีการของวัตถุต้นแบบ
เพื่อสรุป:
ตอบ: ฟังก์ชั่นของวัตถุต้นแบบคือการกำหนดคุณสมบัติและวิธีการที่ใช้ร่วมกันโดยอินสแตนซ์วัตถุทั้งหมด
B: ต้นแบบสำหรับตัวสร้างมันเป็นคุณสมบัติ สำหรับอินสแตนซ์วัตถุมันเป็นวัตถุต้นแบบ
4. เครือข่ายต้นแบบ
คุณสมบัติและวิธีการของวัตถุอาจถูกกำหนดไว้ในตัวเองหรือในวัตถุต้นแบบ เนื่องจากวัตถุต้นแบบเองก็เป็นวัตถุของอินสแตนซ์ของวัตถุและยังมีต้นแบบของตัวเองจึงเกิดห่วงโซ่ต้นแบบ ตัวอย่างเช่น Object A คือต้นแบบของวัตถุ B, Object B คือต้นแบบของวัตถุ C และอื่น ๆ ด้านบนของต้นแบบของวัตถุทั้งหมดคือ Object.prototype นั่นคือวัตถุที่ชี้ไปที่คุณสมบัติต้นแบบของตัวสร้างวัตถุ
แน่นอนว่าวัตถุ object.prototype ยังมีวัตถุต้นแบบของตัวเองนั่นคือวัตถุว่างที่ไม่มีคุณลักษณะและวิธีการใด ๆ และวัตถุ NULL ไม่มีต้นแบบของตัวเอง
1 console.log (object.getPrototypeof (Object.prototype)); //โมฆะ
2 console.log (person.prototype.isprototypeof (boy)) // true
ลักษณะของโซ่ต้นแบบคือ:
ตอบ: เมื่ออ่านคุณสมบัติบางอย่างของวัตถุเครื่องยนต์จาวาสคริปต์แรกจะค้นหาคุณสมบัติของวัตถุเอง หากไม่สามารถพบได้มันจะไปที่ต้นแบบ หากยังไม่สามารถพบได้มันจะไปที่ต้นแบบของต้นแบบ หากยังไม่พบ object.prototype ที่ระดับบนสุด
B: หากวัตถุและต้นแบบของตัวเองกำหนดคุณลักษณะของชื่อเดียวกันคุณลักษณะของวัตถุนั้นจะถูกอ่านก่อนซึ่งเรียกว่า "เอาชนะ"
C: การมองหาคุณลักษณะบางอย่างในระดับห่วงโซ่ต้นแบบขึ้นไปด้านบนมีผลกระทบต่อประสิทธิภาพ ยิ่งระดับวัตถุต้นแบบที่คุณต้องการสูงขึ้นเท่าใดก็ยิ่งส่งผลกระทบต่อประสิทธิภาพมากขึ้นเท่านั้น หากคุณมองหาคุณสมบัติที่ไม่มีอยู่จริงมันจะสำรวจห่วงโซ่ต้นแบบทั้งหมด
อาจไม่ชัดเจนที่จะดูแนวคิดลองมาเป็นตัวอย่าง แต่มันสำคัญมากที่จะเข้าใจแนวคิด
var arr = [1,2,3]; console.log (arr.length); //3console.log (arr.valueof ()) // [1,2,3] console.log (arr.join ('|')) // 1 | 2 | 3ในรหัสข้างต้นมีการกำหนดอาร์เรย์อาร์เรย์โดยมีสามองค์ประกอบในอาร์เรย์ เราไม่ได้เพิ่มแอตทริบิวต์หรือวิธีการใด ๆ ลงในอาร์เรย์ แต่เราไม่ได้รายงานข้อผิดพลาดเมื่อเรียกความยาวเข้าร่วม () และค่าของ ()
แอตทริบิวต์ความยาวนั้นสืบทอดมาจาก array.prototype และเป็นของคุณสมบัติในวัตถุต้นแบบ วิธีการเข้าร่วมนั้นสืบทอดมาจาก Array.prototype และเป็นของวิธีการบนวัตถุต้นแบบ ทั้งสองวิธีนี้ถูกแชร์โดยอาร์เรย์ทั้งหมด เมื่อไม่มีแอตทริบิวต์ความยาวบนวัตถุอินสแตนซ์วัตถุต้นแบบจะถูกค้นหา
วิธีการที่มีค่านั้นสืบทอดมาจาก Object.prototype ก่อนอื่นอาร์เรย์อาร์เรย์ไม่มีวิธีการที่มีค่าดังนั้นค้นหาอาร์เรย์วัตถุต้นแบบ prototype จากนั้นฉันพบว่าไม่มีวิธีการที่มีค่าของอาร์เรย์อาร์เรย์ ในที่สุดค้นหาวัตถุวัตถุ prototype
มาดูคุณสมบัติและวิธีการของอาร์เรย์อาร์เรย์. prototype วัตถุและวัตถุ prototype ตามลำดับ
console.log (object.getownpropertynames (array.prototype)) // ["ความยาว", "tosource", "toString", "tolocalestring", "เข้าร่วม", "ย้อนกลับ", "sort", "push", "pop", "shift", "foreach", "แผนที่", "ตัวกรอง", "reduceright", "บาง", "ทุก", "ค้นหา", "findIndex", "copywithin", "เติม", "รายการ", "keys", "keys", "Value", "constructor", " ["Tosource", "ToString", "Tolocalestring", "Valueof", "Watch", "Unwatch", "Hasownproperty", "Isprototypeof", "Propertyisenumerable", "__definegetter__", " "__proto__", "Constructor"]
ฉันเชื่อว่าเมื่อคุณเห็นสิ่งนี้คุณยังมีความเข้าใจเล็กน้อยเกี่ยวกับต้นแบบ นี่เป็นเรื่องปกติ ท้ายที่สุดมันเป็นแนวคิดที่สำคัญและเป็นนามธรรมใน JS เป็นไปไม่ได้ที่จะควบคุมมันอย่างรวดเร็ว หากคุณกินบทความอีกสองสามบทความคุณอาจเชี่ยวชาญสาระสำคัญ ในบางวิธีมีตัวอย่างชีวิตซึ่งอาจเป็นปัญหาที่ทุกคนจะพบ คุณสามารถดูที่ JS Constructor และวัตถุต้นแบบ
5. แอตทริบิวต์ของตัวสร้าง
วัตถุต้นแบบมีแอตทริบิวต์ตัวสร้างที่ชี้ไปที่ฟังก์ชั่นคอนสตรัคเตอร์ที่วัตถุต้นแบบตั้งอยู่ตามค่าเริ่มต้น
ฟังก์ชัน A () {}; console.log (a.prototype.constructor === a) // trueควรสังเกตว่าต้นแบบเป็นคุณสมบัติของตัวสร้างและตัวสร้างเป็นวัตถุที่ชี้ไปที่คุณสมบัติต้นแบบของตัวสร้างนั่นคือคุณสมบัติของวัตถุต้นแบบ ระวังอย่าสับสน
console.log (a.hasownproperty ('prototype')); // จริง console.log (a.prototype.hasownproperty ('constructor')); //จริงเนื่องจากแอตทริบิวต์ตัวสร้างถูกกำหนดไว้ในวัตถุต้นแบบจึงหมายความว่าสามารถสืบทอดได้โดยวัตถุอินสแตนซ์ทั้งหมด
ฟังก์ชัน A () {}; var a = new a (); console.log (A.Constructor); //a()console.log(a.constructor===a.prototype.constructor);//trueในรหัสข้างต้น A เป็นวัตถุอินสแตนซ์ของตัวสร้าง A แต่ตัวเองไม่มีแอตทริบิวต์ตัวสร้างซึ่งจริง ๆ แล้วกำลังอ่านห่วงโซ่ต้นแบบ
A.prototype.Constructor คุณสมบัติ
5.1: บทบาทของแอตทริบิวต์ตัวสร้าง
ตอบ: กำหนดฟังก์ชั่นตัวสร้างใดที่เป็นวัตถุต้นแบบที่เป็นของ
ฟังก์ชัน A () {}; var a = new a (); console.log (a.constructor === a) // true console.log (a.constructor === อาร์เรย์) // falseรหัสข้างต้นหมายความว่าการใช้คุณสมบัติตัวสร้างจะถูกกำหนดว่าฟังก์ชันตัวสร้างของวัตถุอินสแตนซ์ A คือ A ไม่ใช่อาร์เรย์
B: สร้างอินสแตนซ์อื่นจากอินสแตนซ์
ฟังก์ชัน A () {}; var a = new a (); var b = ใหม่ a.constructor (); console.log (b อินสแตนซ์ของ A); //จริงในรหัสข้างต้น A เป็นวัตถุอินสแตนซ์ของตัวสร้าง A และตัวสร้างสามารถเรียกได้ทางอ้อมจาก A.Constructor
C: เป็นไปได้ที่จะเรียกตัวสร้างของตัวเอง
a.prototype.hello = function () {ส่งคืน this.constructor (); -D: แสดงรูปแบบของการสืบทอดตัวสร้างอื่นจากตัวสร้าง
ฟังก์ชั่นพ่อ () {} ฟังก์ชั่น son () {son.height.constructor.call (นี่); } son.height = พ่อใหม่ ();ในรหัสข้างต้นพ่อและลูกชายเป็นทั้งผู้สร้าง การโทรหาพ่อในบุตรชายคนนี้จะสร้างผลกระทบของลูกชายที่สืบทอดพ่อ
E: เนื่องจากแอตทริบิวต์ตัวสร้างเป็นความสัมพันธ์ระหว่างวัตถุต้นแบบและตัวสร้างเมื่อแก้ไขวัตถุต้นแบบคุณต้องให้ความสนใจกับปัญหาการชี้ของตัวสร้าง
มีสองวิธีแก้ปัญหา: ทั้งสองจุดที่แอตทริบิวต์ตัวสร้างไปยังฟังก์ชั่นคอนสตรัคเตอร์ดั้งเดิมหรือเพียงเพิ่มคุณสมบัติและวิธีการลงในวัตถุต้นแบบเพื่อหลีกเลี่ยงการบิดเบือนอินสแตนซ์
6. อินสแตนซ์ของตัวดำเนินการ
อินสแตนซ์ของตัวดำเนินการส่งคืนค่าบูลีนที่ระบุว่าวัตถุที่ระบุเป็นอินสแตนซ์ของตัวสร้างหรือไม่
ฟังก์ชั่น a () {}; var a = new a (); console.log (อินสแตนซ์ของ A); //จริงเนื่องจากอินสแตนซ์ของวัตถุนั้นใช้ได้กับวัตถุในห่วงโซ่ต้นแบบทั้งหมดวัตถุอินสแตนซ์เดียวกันอาจส่งคืนจริงสำหรับตัวสร้างหลายตัว
ฟังก์ชัน A () {}; var a = new a (); console.log (อินสแตนซ์ของ a); //trueconsole.log(a อินสแตนซ์ของวัตถุ); //จริงโปรดทราบว่าอินสแตนซ์ของวัตถุสามารถใช้สำหรับชนิดข้อมูลที่ซับซ้อนเท่านั้น (อาร์เรย์วัตถุ ฯลฯ ) และไม่สามารถใช้สำหรับชนิดข้อมูลง่าย ๆ (ค่าบูลีนตัวเลขสตริง ฯลฯ )
var x = [1]; var o = {}; var b = true; var c = 'สตริง'; console.log (x อินสแตนซ์ของอาร์เรย์); //trueconsole.log(o อินสแตนซ์ของวัตถุ); // จริง console.log (b อินสแตนซ์ของบูลีน); //falseconsole.log(c string instanceof); //เท็จนอกจากนี้ทั้ง Null และ Undefined ไม่ได้เป็นวัตถุดังนั้นอินสแตนซ์ของการกลับมาเป็นเท็จเสมอ
console.log (วัตถุอินสแตนซ์ null); // false console.log (วัตถุอินสแตนซ์ที่ไม่ได้กำหนด); //เท็จ
การใช้อินสแตนซ์ของตัวดำเนินการคุณยังสามารถแก้ปัญหาอย่างชาญฉลาดในการลืมเพิ่มคำสั่งใหม่เมื่อเรียกตัวสร้าง
ฟังก์ชั่น keith (ชื่อ, ความสูง) {ถ้า (! อินสแตนซ์ของ keith) {ส่งคืน keith ใหม่ (ชื่อ, ความสูง); } this.name = name; this.height = ความสูง;}ในรหัสด้านบนตัวดำเนินการอินสแตนซ์ของตัวดำเนินการเพื่อพิจารณาว่าคำหลักในฟังก์ชั่นร่างกายชี้ไปที่อินสแตนซ์ของตัวสร้างคี ธ หรือไม่ ถ้าไม่หมายความว่าคำสั่งใหม่จะถูกลืม ในเวลานี้ตัวสร้างจะส่งคืนอินสแตนซ์ของวัตถุเพื่อหลีกเลี่ยงผลลัพธ์ที่ไม่คาดคิด
เนื่องจากข้อ จำกัด ด้านพื้นที่ฉันจะแนะนำที่นี่ในขณะนี้
ในการแบ่งปันครั้งต่อไปของฉันฉันจะพูดคุยเกี่ยวกับวิธีการดั้งเดิมของวัตถุต้นแบบเช่น Object.getPrototypeof (), Object.SetPrototypeof () ฯลฯ และแนะนำการเปรียบเทียบวิธีการสำหรับการรับวัตถุดั้งเดิม
ข้างต้นคือคำอธิบายโดยละเอียดของแอตทริบิวต์ต้นแบบ (แนะนำ) ใน JavaScript แนะนำให้คุณทราบโดยบรรณาธิการ ฉันหวังว่ามันจะเป็นประโยชน์กับคุณ