คลาสในตัวเช่น Array, Map และอื่น ๆ ก็สามารถขยายได้เช่นกัน
ตัวอย่างเช่น ที่นี่ PowerArray
สืบทอดมาจาก Array
ดั้งเดิม :
// เพิ่มอีกหนึ่งวิธีลงไป (สามารถทำได้มากกว่านี้) คลาส PowerArray ขยายอาร์เรย์ { isEmpty() { กลับ this.length === 0; - - ให้ arr = PowerArray ใหม่ (1, 2, 5, 10, 50); การแจ้งเตือน (arr.isEmpty()); // เท็จ ให้ filteredArr = arr.filter(item => item >= 10); การแจ้งเตือน (filteredArr); // 10, 50 การแจ้งเตือน (filteredArr.isEmpty()); // เท็จ
โปรดสังเกตสิ่งที่น่าสนใจมาก วิธีการในตัว เช่น filter
, map
และอื่นๆ – ส่งคืนอ็อบเจ็กต์ใหม่ของ PowerArray
ประเภทที่สืบทอดมาทุกประการ การใช้งานภายในใช้คุณสมบัติ constructor
ของวัตถุสำหรับสิ่งนั้น
ในตัวอย่างข้างต้น
arr.constructor === PowerArray
เมื่อ arr.filter()
ถูกเรียก มันจะสร้างอาร์เรย์ใหม่ของผลลัพธ์ภายในโดยใช้ arr.constructor
ไม่ใช่ Array
พื้นฐาน เยี่ยมมากจริงๆ เพราะเราสามารถใช้วิธี PowerArray
ต่อไปกับผลลัพธ์ได้
ยิ่งกว่านั้นเราสามารถปรับแต่งพฤติกรรมนั้นได้
เราสามารถเพิ่ม Symbol.species
ทะเยอทะยานพิเศษให้กับคลาสได้ หากมีอยู่แล้ว ควรส่งคืน Constructor ที่ JavaScript จะใช้ภายในเพื่อสร้างเอนทิตีใหม่ใน map
filter
และอื่นๆ
หากเราต้องการให้เมธอดในตัว เช่น map
หรือ filter
ส่งกลับอาร์เรย์ปกติ เราสามารถส่งคืน Array
ใน Symbol.species
ได้ ดังตัวอย่างที่นี่:
คลาส PowerArray ขยายอาร์เรย์ { isEmpty() { กลับ this.length === 0; - // วิธีการในตัวจะใช้สิ่งนี้เป็นตัวสร้าง รับคงที่ [Symbol.species]() { กลับอาร์เรย์; - - ให้ arr = PowerArray ใหม่ (1, 2, 5, 10, 50); การแจ้งเตือน (arr.isEmpty()); // เท็จ // filter สร้างอาร์เรย์ใหม่โดยใช้ arr.constructor[Symbol.species] เป็นตัวสร้าง ให้ filteredArr = arr.filter(item => item >= 10); // filteredArr ไม่ใช่ PowerArray แต่เป็น Array การแจ้งเตือน (filteredArr.isEmpty()); // ข้อผิดพลาด: filteredArr.isEmpty ไม่ใช่ฟังก์ชัน
อย่างที่คุณเห็นตอนนี้ .filter
ส่งคืน Array
ดังนั้นฟังก์ชันเพิ่มเติมจึงไม่ผ่านอีกต่อไป
คอลเลกชันอื่นๆ ทำงานในลักษณะเดียวกัน
คอลเลกชันอื่นๆ เช่น Map
และ Set
ทำงานเหมือนกัน พวกเขายังใช้ Symbol.species
ออบเจ็กต์บิวท์อินมีวิธีคงที่ของตัวเอง เช่น Object.keys
, Array.isArray
เป็นต้น
อย่างที่เราทราบกันดีอยู่แล้วว่าคลาส Native จะขยายซึ่งกันและกัน ตัวอย่างเช่น Array
ขยาย Object
โดยปกติ เมื่อคลาสหนึ่งขยายออกไปอีกคลาสหนึ่ง ทั้งวิธีการแบบคงที่และแบบไม่คงที่จะได้รับการสืบทอด ซึ่งมีการอธิบายอย่างละเอียดในบทความคุณสมบัติและวิธีการแบบคงที่
แต่คลาสบิวท์อินนั้นเป็นข้อยกเว้น พวกเขาไม่สืบทอดสถิติจากกันและกัน
ตัวอย่างเช่น ทั้ง Array
และ Date
สืบทอดมาจาก Object
ดังนั้นอินสแตนซ์จึงมีเมธอดจาก Object.prototype
แต่ Array.[[Prototype]]
ไม่ได้อ้างอิง Object
ดังนั้นจึงไม่มีเช่น Array.keys()
(หรือ Date.keys()
) วิธีการคงที่
นี่คือโครงสร้างรูปภาพสำหรับ Date
และ Object
:
อย่างที่คุณเห็น ไม่มีการเชื่อมโยงระหว่าง Date
และ Object
พวกมันมีความเป็นอิสระ มีเพียง Date.prototype
เท่านั้นที่สืบทอดมาจาก Object.prototype
นั่นเป็นความแตกต่างที่สำคัญของการสืบทอดระหว่างอ็อบเจ็กต์บิวท์อินเมื่อเปรียบเทียบกับสิ่งที่เราได้รับจาก extends