JavaScript ช่วยให้เราสามารถทำงานกับข้อมูลพื้นฐาน (สตริง ตัวเลข ฯลฯ) ราวกับว่ามันเป็นวัตถุ พวกเขายังมีวิธีการเรียกเช่นนี้ด้วย เราจะศึกษาสิ่งเหล่านั้นเร็วๆ นี้ แต่ก่อนอื่นเรามาดูกันก่อนว่ามันทำงานอย่างไร เพราะแน่นอนว่า พื้นฐานไม่ใช่วัตถุ (และที่นี่เราจะทำให้มันชัดเจนยิ่งขึ้น)
ลองดูความแตกต่างที่สำคัญระหว่างวัตถุดั้งเดิมและวัตถุ
ดั้งเดิม
เป็นค่าประเภทดั้งเดิม
มีประเภทพื้นฐานอยู่ 7 ประเภท: string
, number
, bigint
, boolean
, symbol
, null
และ undefined
วัตถุ
สามารถเก็บค่าต่างๆ ไว้เป็นคุณสมบัติได้
สามารถสร้างได้ด้วย {}
เช่น: {name: "John", age: 30}
มีอ็อบเจ็กต์ประเภทอื่นๆ ใน JavaScript เช่น ฟังก์ชันต่างๆ คืออ็อบเจ็กต์
หนึ่งในสิ่งที่ดีที่สุดเกี่ยวกับวัตถุก็คือเราสามารถจัดเก็บฟังก์ชันเป็นหนึ่งในคุณสมบัติของมันได้
ให้จอห์น = { ชื่อ: "จอห์น" พูดสวัสดี: ฟังก์ชั่น () { alert("สวัสดีเพื่อน!"); - - john.sayHi(); //สวัสดีเพื่อน!
ดังนั้นเราจึงสร้างอ็อบเจ็กต์ john
ด้วยวิธี sayHi
มีออบเจ็กต์บิวท์อินจำนวนมากอยู่แล้ว เช่น ออบเจ็กต์ที่ทำงานกับวันที่ ข้อผิดพลาด องค์ประกอบ HTML เป็นต้น โดยออบเจ็กต์เหล่านี้มีคุณสมบัติและวิธีการที่แตกต่างกัน
แต่คุณสมบัติเหล่านี้มาพร้อมกับค่าใช้จ่าย!
วัตถุนั้น "หนัก" มากกว่าวัตถุดึกดำบรรพ์ พวกเขาต้องการทรัพยากรเพิ่มเติมเพื่อรองรับเครื่องจักรภายใน
นี่คือความขัดแย้งที่ผู้สร้าง JavaScript เผชิญ:
มีหลายสิ่งหลายอย่างที่เราอยากทำกับค่าดั้งเดิม เช่น สตริงหรือตัวเลข คงจะดีถ้าเข้าถึงพวกมันโดยใช้วิธีการต่างๆ
พื้นฐานจะต้องเร็วและเบาที่สุดเท่าที่จะเป็นไปได้
วิธีแก้ปัญหาดูอึดอัดเล็กน้อย แต่นี่คือ:
ดั้งเดิมยังคงเป็นดั้งเดิม ได้ค่าเดียวตามต้องการ
ภาษาช่วยให้สามารถเข้าถึงวิธีการและคุณสมบัติของสตริง ตัวเลข บูลีน และสัญลักษณ์ได้
เพื่อให้ทำงานได้ จึงได้สร้าง "ตัวห่ออ็อบเจ็กต์" พิเศษที่มีฟังก์ชันพิเศษขึ้นมา จากนั้นจึงถูกทำลาย
“ตัวห่ออ็อบเจ็กต์” จะแตกต่างกันไปสำหรับประเภทดั้งเดิมแต่ละประเภท และเรียกว่า: String
, Number
, Boolean
, Symbol
และ BigInt
ดังนั้นพวกเขาจึงมีชุดวิธีการที่แตกต่างกัน
ตัวอย่างเช่น มีเมธอดสตริง str.toUpperCase() ที่ส่งคืน str
ตัวพิมพ์ใหญ่
นี่คือวิธีการทำงาน:
ให้ str = "สวัสดี"; การแจ้งเตือน( str.toUpperCase() ); // สวัสดี
ง่ายใช่มั้ย? นี่คือสิ่งที่เกิดขึ้นจริงใน str.toUpperCase()
:
สตริง str
เป็นค่าดั้งเดิม ดังนั้นในขณะที่เข้าถึงคุณสมบัติของมัน ออบเจ็กต์พิเศษจะถูกสร้างขึ้นโดยรู้ค่าของสตริง และมีเมธอดที่มีประโยชน์ เช่น toUpperCase()
เมธอดนั้นรันและส่งคืนสตริงใหม่ (แสดงโดย alert
)
วัตถุพิเศษจะถูกทำลาย เหลือเพียง str
ดั้งเดิมเท่านั้น
ดังนั้นวิธีดั้งเดิมสามารถให้วิธีการได้ แต่ก็ยังมีน้ำหนักเบาอยู่
เอ็นจิ้น JavaScript ปรับกระบวนการนี้ให้เหมาะสมอย่างมาก มันอาจจะข้ามการสร้างวัตถุพิเศษไปเลยก็ได้ แต่ยังคงต้องเป็นไปตามข้อกำหนดและประพฤติตนเสมือนเป็นการสร้างขึ้นมา
ตัวเลขมีวิธีของตัวเอง เช่น toFixed(n) ปัดเศษตัวเลขตามความแม่นยำที่กำหนด:
ให้ n = 1.23456; การแจ้งเตือน ( n.toFixed(2) ); // 1.23
เราจะดูวิธีการเฉพาะเจาะจงมากขึ้นในบทตัวเลขและสตริง
Constructors String/Number/Boolean
มีไว้สำหรับใช้ภายในเท่านั้น
บางภาษาเช่น Java อนุญาตให้เราสร้าง "วัตถุ wrapper" สำหรับวัตถุดั้งเดิมได้อย่างชัดเจนโดยใช้ไวยากรณ์เช่น new Number(1)
หรือ new Boolean(false)
ใน JavaScript นั่นอาจเป็นไปได้ด้วยเหตุผลทางประวัติศาสตร์ แต่ ไม่แนะนำ อย่างยิ่ง สิ่งต่างๆ จะเกิดความบ้าคลั่งในหลายๆ แห่ง
ตัวอย่างเช่น:
การแจ้งเตือน (ประเภท 0 ); // "ตัวเลข" alert( ประเภทของหมายเลขใหม่ (0) ); // "วัตถุ"!
ออบเจ็กต์เป็นจริงเสมอใน if
ดังนั้นการแจ้งเตือนจะปรากฏขึ้นที่นี่:
ให้ศูนย์ = หมายเลขใหม่ (0); ถ้า (ศูนย์) { // ศูนย์เป็นจริง เพราะเป็นวัตถุ alert( "ศูนย์คือความจริง!?!" ); -
ในทางกลับกัน การใช้ฟังก์ชันเดียวกัน String/Number/Boolean
โดยไม่มี new
ก็ถือว่าดีและมีประโยชน์อย่างยิ่ง โดยจะแปลงค่าเป็นประเภทที่สอดคล้องกัน: เป็นสตริง ตัวเลข หรือบูลีน (ดั้งเดิม)
ตัวอย่างเช่น สิ่งนี้ถูกต้องทั้งหมด:
ให้ num = Number("123"); // แปลงสตริงให้เป็นตัวเลข
null/unknown ไม่มีวิธีการ
ค่าพื้นฐานพิเศษ null
และ undefined
เป็นข้อยกเว้น พวกเขาไม่มี "วัตถุ wrapper" ที่สอดคล้องกันและไม่มีวิธีการ เรียกได้ว่าเป็น "พวกดั้งเดิมที่สุด"
ความพยายามในการเข้าถึงคุณสมบัติของค่าดังกล่าวจะทำให้เกิดข้อผิดพลาด:
การแจ้งเตือน (null.test); // ข้อผิดพลาด
Primitives ยกเว้น null
และ undefined
มีวิธีการที่เป็นประโยชน์มากมาย เราจะศึกษาสิ่งเหล่านั้นในบทต่อๆ ไป
อย่างเป็นทางการ วิธีการเหล่านี้ทำงานผ่านอ็อบเจ็กต์ชั่วคราว แต่เอ็นจิ้น JavaScript ได้รับการปรับแต่งอย่างดีเพื่อเพิ่มประสิทธิภาพภายใน ดังนั้นจึงไม่แพงที่จะเรียกใช้
ความสำคัญ: 5
พิจารณารหัสต่อไปนี้:
ให้ str = "สวัสดี"; str.ทดสอบ = 5; การแจ้งเตือน (str.test);
คุณคิดว่ามันจะได้ผลไหม? จะแสดงอะไรบ้าง?
ลองเรียกใช้:
ให้ str = "สวัสดี"; str.ทดสอบ = 5; - การแจ้งเตือน (str.test);
ขึ้นอยู่กับว่าคุณ use strict
หรือไม่ ผลลัพธ์อาจเป็น:
undefined
(ไม่มีโหมดเข้มงวด)
เกิดข้อผิดพลาด (โหมดเข้มงวด)
ทำไม มาเล่นซ้ำสิ่งที่เกิดขึ้นที่บรรทัด (*)
:
เมื่อเข้าถึงคุณสมบัติของ str
แล้ว "วัตถุ wrapper" จะถูกสร้างขึ้น
ในโหมดเข้มงวด การเขียนลงไปถือเป็นข้อผิดพลาด
มิฉะนั้น การดำเนินการด้วยคุณสมบัติจะดำเนินต่อไป อ็อบเจ็กต์จะได้รับคุณสมบัติ test
แต่หลังจากนั้น "อ็อบเจ็กต์ wrapper" จะหายไป ดังนั้นในบรรทัดสุดท้าย str
จึงไม่มีร่องรอยของคุณสมบัติ
ตัวอย่างนี้แสดงให้เห็นชัดเจนว่าวัตถุดั้งเดิมไม่ใช่วัตถุ
พวกเขาไม่สามารถเก็บข้อมูลเพิ่มเติมได้