JavaScript เป็นภาษาการเขียนโปรแกรมที่สองที่ฉันเข้ามาติดต่อหลังจากภาษา C ในช่วงวันหยุดฤดูร้อนน้องใหม่ของฉันฉันพบการเขียนโปรแกรม JavaScript ที่เขียนโดยภาษาจีนในห้องสมุด ในเวลานั้นฉันเกือบจะเป็นมือใหม่ในการเขียนโปรแกรม นอกจากนี้หนังสือเล่มนี้ไม่ได้กล่าวถึงกลไกการเขียนโปรแกรมของ JavaScript เลยและมีคำพูดที่ทำให้เข้าใจผิด ฉันมักจะมีความเข้าใจผิดอย่างลึกซึ้งเกี่ยวกับ JavaScript โดยเชื่อว่า JavaScript เป็นเพียงภาษาที่มุ่งเน้นวัตถุที่ทำงานบนเบราว์เซอร์ ฉันจะเขียนบทความนี้ที่สับสนและเข้าใจผิดใน JavaScript แน่นอนเนื่องจากระดับ จำกัด ของผู้เขียนและไม่มีประสบการณ์การพัฒนามีการละเว้นอย่างหลีกเลี่ยงไม่ได้และฉันหวังว่าการวิจารณ์และการแก้ไขจะเกิดขึ้น
วัตถุจาวาสคริปต์
วัตถุคืออะไร
คำหลักใหม่สามารถมองเห็นได้ทุกที่ในรหัส JavaScript ซึ่งเป็นเรื่องง่ายที่จะเข้าใจผิดว่า JavaScript เป็นภาษาที่ใช้การสืบทอดในชั้นเรียนเช่นเดียวกับ Java แต่นี่ไม่ใช่กรณี ไม่มีคลาสใน JavaScript ดังนั้นวัตถุของ JavaScript ที่ไม่ใช่คลาสคืออะไร? ในแง่หนึ่งวัตถุ JavaScript เป็นพจนานุกรม (ตารางแฮช) ใน Python และเป็นคู่คีย์-ค่าคล้ายกับนี้:
me = {"fisrtname": "Seek", "LastName": "Truth", "getName": function () {return this.firstname+this.lastname; // สิ่งนี้เทียบเท่ากับตัวชี้กับวัตถุนี้}}นี่เป็นความเข้าใจผิดที่ค่อนข้าง เมื่อฉันเห็นครั้งแรกฉันรู้สึกว่าเข้าใจยากเล็กน้อย แต่ฉันก็ยังรู้สึกว่ามันสมเหตุสมผลที่จะใช้อย่างระมัดระวัง เราสามารถใช้ตัวดำเนินการ [] เพื่อรับองค์ประกอบเช่น Python หรือใช้ โอเปอเรเตอร์เพื่อรับองค์ประกอบ:
me.firstname // => seekMe ["LastName"] // => TruthMe.getName () // => SeekTruth
ผู้ให้บริการใหม่
เนื่องจากไม่มีคลาสใน JavaScript ผู้ให้บริการใหม่กำลังทำอะไร? นี่เป็นหนึ่งในแง่มุมที่ทำให้เข้าใจผิดที่สุดของการออกแบบ JavaScript JavaScript เป็นภาษาการเขียนโปรแกรมที่ใช้งานได้ ฟังก์ชั่นใน JavaScript เป็นพลเมืองชั้นหนึ่งและฟังก์ชั่นใน JavaScript ก็เป็นวัตถุเช่นกัน วัตถุฟังก์ชั่นจะถูกเพิ่มลงในแอตทริบิวต์การโทรเมื่อสร้างขึ้น สิ่งที่มีข้อผิดพลาดมากกว่านั้นคือมีสองวิธีในการเรียกใช้ฟังก์ชัน JavaScript หนึ่งคือการโทรด้วยคำหลักใหม่และอื่น ๆ คือการโทรโดยไม่ต้องใช้คำหลักใหม่ อดีตจะส่งคืนวัตถุและหลังจะส่งคืนเนื้อหาของคำสั่งคืน พิจารณาฟังก์ชั่นต่อไปนี้:
ฟังก์ชั่น obj (ชื่อ) {this.name = name; ชื่อคืน;}หากเราใช้ตัวดำเนินการใหม่เพื่อโทร:
obj = new obj ("seektruth") // obj จะเป็นวัตถุ: {"ชื่อ": "seektruth"}
ถ้าเราโทรโดยตรง:
obj = obj ("seektruth") // obj จะเป็นสตริง: "seektruth"
มันเป็นการออกแบบที่ยุ่งยากมาก เมื่อเราโทรเราต้องแยกแยะว่าเราจำเป็นต้องใช้ใหม่หรือไม่ โดยทั่วไปฟังก์ชั่นที่จำเป็นต้องใช้คำหลักใหม่จะเริ่มต้นด้วยการใช้อักษรตัวพิมพ์ใหญ่
อีกสิ่งที่ยุ่งยากคือถ้าค่าส่งคืนที่ส่งคืนเป็นวัตถุ:
ฟังก์ชั่น obj (ชื่อ) {this.name = name; กลับ {};}ด้วยวิธีนี้ไม่ว่าเราจะเรียกผู้ให้บริการใหม่หรือไม่เราจะส่งคืนค่าในคำสั่ง Return:
ใหม่ obj ("seektruth") // => {} obj ("seektruth") // => {}มันออกแบบอะไร ...
การสืบทอดวัตถุ
ต้นแบบ
ดังที่ได้กล่าวไว้ก่อนหน้านี้ไม่มีชั้นเรียนใน JavaScript ดังนั้น JavaScript จึงใช้การสืบทอดได้อย่างไร คำตอบคือผ่านห่วงโซ่ต้นแบบ ใน JavaScript แต่ละวัตถุมีต้นแบบ เมื่อสร้างวัตถุหากไม่ได้ระบุต้นแบบที่สืบทอดมาจากวัตถุคือ Object.prototype วัตถุฟังก์ชั่นจะสืบทอดฟังก์ชั่น.
Object.prototype // => {} function.prototype // => [ฟังก์ชั่น]เราสามารถดูต้นแบบของวัตถุผ่านความคุ้นเคย __proto__ ของวัตถุ:
a = {} a .__ proto__ // => {}JavaScript ใช้การสืบทอดโดยการระบุต้นแบบของวัตถุ มีสามวิธีหลักในการระบุต้นแบบของวัตถุ หนึ่งคือการระบุต้นแบบในคอนสตรัคเตอร์ที่สองคือการแก้ไขแอตทริบิวต์ __proto__ ของวัตถุโดยตรงและที่สามคือการใช้ฟังก์ชัน Object.create ลองมาดูกัน
ระบุต้นแบบในตัวสร้าง
เราสามารถระบุต้นแบบของวัตถุในตัวสร้าง:
me = {"FirstName": "Seek", "LastName": "Truth", "getName": function () {return this.firstname+this.lastname; // สิ่งนี้เทียบเท่ากับตัวชี้ไปยังวัตถุนี้}} ฟังก์ชั่น obj (ชื่อ) {this.firstName = ชื่อ; นี้ .__ proto__ = ฉัน; // ระบุต้นแบบเป็นวัตถุ ME}หลังจากระบุต้นแบบเราสามารถเข้าถึงคุณสมบัติของต้นแบบหลังจากสร้างวัตถุใหม่:
obj = ใหม่ obj ("foo"); // => {firstName: 'foo'} obj.firstname // => fooobj.lastname // => TruthObj.getName () // => "footruth"เมื่อเข้าถึงวัตถุคุณจะพยายามค้นหาคุณสมบัติในวัตถุที่แก้ไขก่อน ถ้าไม่กลับไปที่ต้นแบบเพื่อค้นหาจนกระทั่ง Object.prototype หากเราเขียนคุณสมบัติ (วิธีการ) ใหม่ในต้นแบบในวัตถุใหม่จากนั้นเมื่อเราใช้มันคุณสมบัติที่เขียนขึ้นใหม่ (วิธีการ) จะเขียนทับคำจำกัดความในต้นแบบซึ่งเป็นฟังก์ชั่นที่มากเกินไปในภาษาที่ใช้คลาส
โปรดทราบว่าหากคุณสมบัตินามสกุลของวัตถุต้นแบบ ME มีการเปลี่ยนแปลงเนื่องจากวัตถุ OBJ กำลังมองหาคุณสมบัติในต้นแบบคุณสมบัตินามสกุลของวัตถุ OBJ จะเปลี่ยน:
me.lastName = "me" obj.lastname // => "me" obj.getName () // => "foome"
เปลี่ยนต้นแบบของวัตถุโดยตรง
นอกจากนี้เรายังสามารถระบุ (เปลี่ยน) ต้นแบบของวัตถุได้โดยตรง:
obj2 = {} obj2 .__ proto__ = meobj2.firstname // => seekobj2.lastname // => "ฉัน" obj2.getName () // => "seekme"ใช้ฟังก์ชัน Object.create
แม้ว่าสองวิธีแรกสามารถแก้ปัญหาได้ แต่วิธีการเขียนทั้งสองนี้ไม่ได้สง่างามเพราะ JavaScript ไม่ใช่ภาษาในชั้นเรียนและวิธีการเขียนครั้งแรกนั้นง่ายต่อการเข้าใจผิด Crockford ผู้เขียน Essence of JavaScript Language เชื่อว่าใหม่ไม่ควรปรากฏในภาษา JavaScript และขอแนะนำให้ใช้ฟังก์ชัน Object.create เพื่อสร้างวัตถุตามต้นแบบ การใช้งานฟังก์ชั่นการสร้างวัตถุนั้นง่ายมาก:
obj3 = object.create (me) // สร้างวัตถุใหม่กับฉันเป็นต้นแบบ obj3.firstname // => seekobj3.lastname // => "me" obj3.getName () // => "seekme"
obj3 = object.create (me) เทียบเท่ากับ obj2 = {}; obj2.proto = me แต่อดีตเขียนขึ้นอย่างสง่างามและง่ายกว่าที่จะเข้าใจ
สรุป
ในฐานะที่เป็นภาษาการเขียนโปรแกรมที่ใช้ต้นแบบและใช้งานได้ JavaScript มีความสง่างามและพลังมากมายในการออกแบบ แต่ในขณะเดียวกันก็มีจำนวนมากและหลุมพราง สำหรับมากที่สุด JavaScript ยังเป็นภาษาที่เข้าใจผิดมากที่สุด หลังจากเรียนรู้กลไกการสืบทอดวัตถุของ JavaScript ฉันรู้สึกว่าระดับของฉันดีขึ้นมาก
การอภิปรายสั้น ๆ เกี่ยวกับวัตถุ JavaScript และการสืบทอดเป็นเนื้อหาทั้งหมดที่ฉันแบ่งปันกับคุณ ฉันหวังว่ามันจะให้ข้อมูลอ้างอิงและฉันหวังว่าคุณจะสนับสนุน wulin.com มากขึ้น