กลับไปหน้าบทความ

อ่าน 49 นาที

ไวยากรณ์ JavaScript

ไวยากรณ์ของJavaScriptคือชุดของกฎที่กำหนดโครงสร้างที่ถูกต้องของโปรแกรม JavaScript

ไวยากรณ์ JavaScript

ตัวอย่างโค้ดJavaScript ที่ ไฮไลต์ คำสำคัญ ด้วยสีต่างๆ

ไวยากรณ์ของJavaScriptคือชุดของกฎที่กำหนดโครงสร้างที่ถูกต้องของโปรแกรม JavaScript

ตัวอย่างด้านล่างนี้ใช้console.log()ฟังก์ชันที่มีอยู่ในเบราว์เซอร์ส่วนใหญ่สำหรับการ แสดงผลข้อความมาตรฐาน

ไลบรารีมาตรฐานของ JavaScript ขาดฟังก์ชันแสดงข้อความมาตรฐานอย่างเป็นทางการ (ยกเว้น `<a href="..."> document.write`) เนื่องจาก JavaScript ส่วนใหญ่ใช้สำหรับการเขียนสคริปต์ฝั่งไคลเอ็นต์ภายในเว็บเบราว์เซอร์ สมัยใหม่ และเว็บเบราว์เซอร์เกือบทั้งหมดมีฟังก์ชัน `<a href="...">` ดังนั้นจึงalertสามารถใช้ `<a href="...">` ได้เช่นกัน แต่ไม่นิยมใช้กันทั่วไป

TypeScriptซึ่งเป็นส่วนขยายของ JavaScript ด้วยการระบุประเภทข้อมูลและคุณสมบัติเพิ่มเติม มีไวยากรณ์เหมือนกันกับ JavaScript รวมทั้งคุณสมบัติเพิ่มเติมของตัวเองด้วย

ต้นกำเนิด

โค้ด JavaScript ที่แสดงวันในสัปดาห์ในเบราว์เซอร์

Brendan Eichสรุปที่มาของไวยากรณ์ในย่อหน้าแรกของข้อกำหนด JavaScript 1.1 [ 1 ] [ 2 ]ดังนี้:

JavaScript ยืมไวยากรณ์ส่วนใหญ่มาจากJavaแต่ก็ยังได้รับอิทธิพลจากAwkและPerl ด้วย โดยมีอิทธิพลทางอ้อมบางส่วนจากSelfในระบบต้นแบบของอ็อบเจ็กต์

ไวยากรณ์ของ JavaScript ส่วนใหญ่ได้มาจากไวยากรณ์ของ Javaซึ่งได้มาจาก ไวยากรณ์ ของ CและC++อีก ทีหนึ่ง

พื้นฐาน

คำสำคัญ

คำสงวน

คำต่อไปนี้เป็นคำหลักและไม่สามารถใช้เป็นคำระบุตัวตนได้ในทุกกรณี

  • async
  • break
  • case
  • catch
  • class
  • const
  • continue
  • debugger
  • default
  • delete
  • do
  • else
  • enum
  • eval
  • export
  • extends
  • finally
  • for
  • function
  • if
  • implements
  • import
  • in
  • instanceof
  • interface
  • let
  • new
  • package
  • private
  • protected
  • public
  • return
  • static
  • super
  • switch
  • this
  • throw
  • try
  • typeof
  • using
  • var
  • void
  • while
  • with
  • yield

คำสงวนสำหรับค่าตามตัวอักษร

คำต่อไปนี้หมายถึงความหมายตามตัวอักษรที่ใช้ในภาษา

  • true
  • false
  • null

JavaScript ยังกำหนดค่าคงที่ส่วนกลางต่อไปนี้ ซึ่งไม่ใช่คีย์เวิร์ด

  • NaN
  • Infinity
  • undefined
  • globalThis

ลบคำหลักออก

คำต่อไปนี้ ซึ่งส่วนใหญ่เกี่ยวข้องกับภาษา Java ถูกลบออกจาก มาตรฐาน ECMAScript 5/6:

  • abstract
  • boolean
  • byte
  • char
  • double
  • final
  • float
  • goto
  • int
  • long
  • native
  • short
  • synchronized
  • throws
  • transient
  • volatile

คีย์เวิร์ด TypeScript

คำต่อไปนี้เป็นคำสำคัญใน TypeScript

  • abstract
  • any
  • as
  • declare
  • infer
  • keyof
  • module
  • namespace
  • never
  • readonly
  • type
  • unknown

การคำนึงถึงตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก

JavaScript เป็นภาษาที่คำนึงถึงตัวพิมพ์ใหญ่และตัวพิมพ์เล็กโดยทั่วไปแล้ว ชื่อของคอนสตรัคเตอร์ มักจะขึ้นต้น ด้วย ตัวอักษรพิมพ์ ใหญ่และชื่อของฟังก์ชันหรือตัวแปรจะขึ้นต้นด้วยตัวอักษรพิมพ์เล็ก

ตัวอย่าง:

var a = 5 ; console.log ( a ) ; // 5 console.log ( A ); // เกิด ข้อผิดพลาด ReferenceError: A ไม่ได้ถูกกำหนด

ช่องว่างและเครื่องหมายอัฒภาค

ต่างจากใน ภาษา Cช่องว่างในซอร์สโค้ด JavaScript สามารถส่งผลกระทบต่อความหมายโดยตรงได้เครื่องหมายเซมิโคลอนจะจบคำสั่งใน JavaScript เนื่องจากการแทรกเซมิโคลอนอัตโนมัติ (ASI) คำสั่งบางคำสั่งที่มีรูปแบบถูกต้องเมื่อมีการแยกวิเคราะห์ บรรทัดใหม่ จะถือว่าสมบูรณ์ราวกับว่ามีการแทรกเซมิโคลอนไว้ก่อนบรรทัดใหม่ ผู้เชี่ยวชาญบางคนแนะนำให้ใส่เซมิโคลอนเพื่อจบคำสั่งอย่างชัดเจน เนื่องจากอาจช่วยลดผลกระทบที่ไม่พึงประสงค์ของการแทรกเซมิโคลอนอัตโนมัติได้[ 3 ]

มีประเด็นอยู่สองประการ: โทเค็นห้าตัวสามารถเริ่มต้นประโยคหรือเป็นส่วนขยายของประโยคที่สมบูรณ์ได้ และกฎการผลิตแบบจำกัดห้าข้อ ซึ่งไม่อนุญาตให้มีการขึ้นบรรทัดใหม่ในบางตำแหน่ง ซึ่งอาจส่งผลให้การวิเคราะห์ไวยากรณ์ไม่ถูกต้อง

สัญลักษณ์ที่มีปัญหา 5 ตัว ได้แก่ วงเล็บเปิด " (", วงเล็บเหลี่ยมเปิด " [", เครื่องหมายทับ " /", เครื่องหมายบวก " +", และเครื่องหมายลบ " -" ในบรรดาสัญลักษณ์เหล่านี้ วงเล็บเปิดมักพบได้บ่อยใน รูปแบบ นิพจน์ฟังก์ชันที่เรียกใช้ทันทีวงเล็บเหลี่ยมเปิดพบได้บ้าง ในขณะที่สัญลักษณ์อื่นๆ พบได้ค่อนข้างน้อย ตัวอย่างเช่น:

a = b + c ( d + e ). foo ()// ดำเนินการดังนี้: // a = b + c(d + e).foo();

พร้อมข้อเสนอแนะว่าควรปิดท้ายประโยคก่อนหน้าด้วยเครื่องหมายเซมิโคลอน

บางคนแนะนำให้ใช้เครื่องหมาย เซมิโคลอน นำหน้าบรรทัดที่ขึ้นต้นด้วย ' (' หรือ ' [' เพื่อป้องกันไม่ให้บรรทัดนั้นเชื่อมต่อกับบรรทัดก่อนหน้าโดยไม่ได้ตั้งใจ วิธีนี้เรียกว่าเซมิโคลอนป้องกันและใช้เพราะมิเช่นนั้นโค้ดอาจเกิดความกำกวมเมื่อมีการจัดเรียงใหม่ ตัวอย่างเช่น:

a = b + c ( d + e ). foo ()// ดำเนินการดังนี้: // a = b + c; // (d + e).foo();

เครื่องหมายเซมิโคลอนนำหน้าบางครั้งก็ถูกใช้ที่จุดเริ่มต้นของไลบรารี JavaScript ในกรณีที่ไลบรารีนั้นถูกนำไปต่อกับไลบรารีอื่นที่ละเว้นเครื่องหมายเซมิโคลอนปิดท้าย เพราะอาจทำให้เกิดความกำกวมในคำสั่งเริ่มต้นได้ ในกรณีที่การวางเครื่องหมายเซมิโคลอนผิดปกติเกิดขึ้น อาจเป็นการดีกว่าที่จะใส่เครื่องหมายเซมิโคลอนด้วยตนเองที่ท้ายคำสั่ง

กฎการผลิตที่จำกัดทั้งห้าข้อ ได้แก่return, throw, break, continue, และการเพิ่ม/ลดค่าหลังการดำเนินการ ในทุกกรณี การใส่เครื่องหมายเซมิโคลอนไม่ได้แก้ปัญหา แต่ทำให้ไวยากรณ์ที่แยกวิเคราะห์ชัดเจนขึ้น ทำให้ตรวจจับข้อผิดพลาดได้ง่ายขึ้นreturnและthrowรับค่าที่เป็นตัวเลือก ในขณะที่breakและcontinueรับป้ายกำกับที่เป็นตัวเลือก ในทุกกรณี คำแนะนำคือให้เก็บค่าหรือป้ายกำกับไว้ในบรรทัดเดียวกันกับคำสั่ง ซึ่งมักจะปรากฏในคำสั่ง return ที่อาจส่งคืนค่าลิเทอรัลออบเจ็กต์ขนาดใหญ่ ซึ่งอาจถูกวางไว้ในบรรทัดใหม่โดยไม่ได้ตั้งใจ สำหรับการเพิ่ม/ลดค่าหลังการดำเนินการ อาจมีความกำกวมกับการเพิ่ม/ลดค่าก่อนการดำเนินการ และขอแนะนำให้เก็บไว้บนบรรทัดเดียวกันอีกครั้ง

ส่งคืนค่าa + b ;// ส่งคืนค่า undefined ถือว่าเป็น: // return; // a + b; // ควรเขียนเป็น: // return a + b;

ความคิดเห็น

รูปแบบ การเขียนคำอธิบายประกอบเหมือนกับใน ภาษา C++ , Swiftและภาษาโปรแกรมอื่นๆ

ข้อความแสดงความคิดเห็นแบบบรรทัดเดียวเริ่มต้นด้วย//และต่อเนื่องไปจนถึงท้ายบรรทัด นอกจากนี้ยังมีข้อความแสดงความคิดเห็นอีกประเภทหนึ่ง ซึ่งเริ่มต้นด้วย/*และจบด้วย*/และสามารถใช้สำหรับข้อความแสดงความคิดเห็นแบบหลายบรรทัดได้

ความคิดเห็นประเภทที่สามคือความคิดเห็นแบบ hashbang ซึ่งเริ่มต้น#!และต่อเนื่องไปจนถึงท้ายบรรทัด ความคิดเห็นประเภทนี้ใช้ได้เฉพาะที่จุดเริ่มต้นของไฟล์และมีจุดประสงค์เพื่อใช้ในสภาพแวดล้อมCLI [ 4 ]

# ! แฮชแบงคอมเมนต์// ข้อความแสดงความคิดเห็นบรรทัดเดียว/* ข้อความแสดงความคิดเห็นหลายบรรทัด */

ตัวแปร

ตัวแปรใน JavaScript มาตรฐานไม่มีประเภทกำกับ ดังนั้นค่าใดๆ (แต่ละค่ามีประเภท) สามารถเก็บไว้ในตัวแปรใดก็ได้ ตั้งแต่ES6 ซึ่ง เป็นเวอร์ชันที่ 6 ของภาษา ตัวแปรสามารถประกาศได้ด้วย `var` varสำหรับตัวแปรที่มีขอบเขตในฟังก์ชัน และ `var` letหรือ ` var` constซึ่งใช้สำหรับ ตัวแปร ระดับบล็อกก่อน ES6 ตัวแปรสามารถประกาศได้ด้วยvarคำสั่ง `var` เท่านั้น ค่าที่กำหนดให้กับตัวแปรที่ประกาศด้วย `var` constไม่สามารถเปลี่ยนแปลงได้ แต่คุณสมบัติของตัวแปรสามารถเปลี่ยนแปลงได้varไม่ควรใช้ `var` อีกต่อไปเนื่องจาก `var` letและconst`var` รองรับโดยเบราว์เซอร์สมัยใหม่[ 5 ]ตัวระบุของตัวแปรต้องขึ้นต้นด้วยตัวอักษร เครื่องหมายขีดล่าง ( __) หรือเครื่องหมายดอลลาร์ (_ $) ในขณะที่อักขระถัดไปสามารถเป็นตัวเลขได้ ( 0-9) JavaScript มีความไวต่อตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก ดังนั้นตัวพิมพ์ใหญ่ " A " ถึง " Z " จึงแตกต่างจากตัวพิมพ์เล็ก " a " ถึง " z "

ตั้งแต่ JavaScript 1.5 เป็นต้นไปสามารถใช้ ตัวอักษร ISO 8859-1หรือUnicode (หรือ ลำดับการหลีกเลี่ยง Unicode) ในตัวระบุได้ [ 6 ]ในการใช้งาน JavaScript บางอย่าง สามารถใช้ เครื่องหมาย @ ในตัวระบุได้ แต่ขัดกับข้อกำหนดและไม่ได้รับการสนับสนุนในการใช้งานเวอร์ชันใหม่กว่า \uXXXX

การสำรวจและการยก

ตัวแปรที่ประกาศด้วย `@` varจะมีขอบเขตตามพจนานุกรมที่ระดับฟังก์ชันในขณะที่ตัวแปรที่มี `@` letหรือ `@ const` จะมี ขอบเขต ที่ระดับบล็อกเนื่องจากมีการประมวลผลการประกาศก่อนที่โค้ดใดๆ จะถูกดำเนินการ ตัวแปรจึงสามารถกำหนดค่าและใช้งานได้ก่อนที่จะมีการประกาศในโค้ด[ 7 ]สิ่งนี้เรียกว่าการยกขึ้น (hoisting)และเทียบเท่ากับการประกาศตัวแปรล่วงหน้าที่ด้านบนของฟังก์ชันหรือบล็อก [ 8 ]

เมื่อใช้ คำสั่ง var`set` let, `set` และconst`set` เฉพาะการประกาศตัวแปรเท่านั้นที่จะถูกยกขึ้นไป (hoisted) ส่วนการกำหนดค่าจะไม่ถูกยกขึ้นไปด้วย ดังนั้นคำสั่ง `set` ที่อยู่ตรงกลางฟังก์ชันจึงเทียบเท่ากับคำสั่งประกาศตัวแปรที่อยู่ด้านบนสุดของฟังก์ชัน และคำสั่งกำหนดค่าตัวแปรที่อยู่ตรงกลางฟังก์ชันนั้น หมายความว่าไม่สามารถเข้าถึงค่าได้ก่อนที่จะมีการประกาศตัวแปร การอ้างอิงไปข้างหน้าจึงเป็นไปไม่ได้ค่าของตัวแปรจะคงอยู่จนกว่าจะมีการกำหนดค่าเริ่มต้น ตัวแปรที่ประกาศด้วย ` set` หรือ ` set` จะไม่สามารถเข้าถึงได้จนกว่าจะได้รับการกำหนดค่าเริ่มต้น ดังนั้นการอ้างอิงตัวแปรดังกล่าวด้วย `set` จะทำให้เกิดข้อผิดพลาด varx=1varxx=1varundefinedletconst

การประกาศฟังก์ชัน ซึ่งเป็นการประกาศตัวแปรและกำหนดฟังก์ชันให้กับตัวแปรนั้น คล้ายกับคำสั่งตัวแปร แต่เพิ่มเติมจากการยกการประกาศขึ้นไปด้านบนแล้ว ยังยกการกำหนดค่าขึ้นไปด้านบนด้วย – ราวกับว่าคำสั่งทั้งหมดปรากฏอยู่ด้านบนสุดของฟังก์ชันที่ครอบคลุม – ดังนั้นจึงสามารถอ้างอิงไปข้างหน้าได้: ตำแหน่งของคำสั่งฟังก์ชันภายในฟังก์ชันที่ครอบคลุมนั้นไม่สำคัญ ซึ่งแตกต่างจากการกำหนดค่าฟังก์ชันให้กับตัวแปรใน คำสั่ง var`if`, let`if`, `if` หรือ ` if`const

ตัวอย่างเช่น

var func = function () { .. } // การประกาศจะถูกยกขึ้นเท่านั้นfunction func () { .. } // การประกาศและการกำหนดค่าจะถูกยกขึ้น

การกำหนดขอบเขตของบล็อกสามารถทำได้โดยการห่อบล็อกทั้งหมดไว้ในฟังก์ชันแล้วจึงเรียกใช้ฟังก์ชันนั้น ซึ่งเรียกว่า รูปแบบ นิพจน์ฟังก์ชันที่เรียกใช้ทันทีหรือโดยการประกาศตัวแปรโดยใช้letคำหลัก

การประกาศและการมอบหมาย

ตัวแปรที่ประกาศอยู่นอกขอบเขตจะเป็นตัวแปรส่วนกลาง (global ) หากตัวแปรถูกประกาศในขอบเขตที่สูงกว่า ขอบเขตย่อยก็สามารถเข้าถึงตัวแปรนั้นได้

เมื่อ JavaScript พยายามค้นหาตัวระบุ มันจะค้นหาในขอบเขตท้องถิ่นก่อน หากไม่พบตัวระบุนี้ มันจะค้นหาในขอบเขตภายนอกถัดไป และทำเช่นนี้ไปเรื่อยๆ ตามลำดับขอบเขตจนกระทั่งถึงขอบเขตทั่วโลกซึ่งเป็นที่อยู่ของตัวแปรทั่วโลก หากยังไม่พบอีก JavaScript จะแสดงReferenceErrorข้อผิดพลาด

เมื่อกำหนดตัวระบุ JavaScript จะดำเนินการตามกระบวนการเดียวกันเพื่อดึงตัวระบุนี้ ยกเว้นว่าหากไม่พบในขอบเขตทั่วโลกมันจะสร้าง "ตัวแปร" ในขอบเขตที่สร้างขึ้น[ 9 ]ผลที่ตามมาคือ ตัวแปรที่ไม่เคยประกาศจะกลายเป็นตัวแปรทั่วโลกหากมีการกำหนดค่า การประกาศตัวแปร (ด้วยคำหลักvar) ในขอบเขตทั่วโลก (เช่น นอกตัวฟังก์ชันใดๆ (หรือบล็อกในกรณีของ let/const)) การกำหนดค่าตัวระบุที่ไม่เคยประกาศ หรือการเพิ่มคุณสมบัติให้กับออบเจ็กต์ทั่วโลก (โดยปกติคือ window ) จะสร้างตัวแปรทั่วโลกใหม่ด้วย

โปรดทราบว่า โหมดเข้มงวด (strict mode)ของ JavaScript ห้ามการกำหนดค่าให้กับตัวแปรที่ไม่ได้ประกาศไว้ ซึ่งจะช่วยหลีกเลี่ยงการปนเปื้อนของเนมสเปซส่วนกลาง

ตัวอย่าง

ต่อไปนี้เป็นตัวอย่างของการประกาศตัวแปรและขอบเขตการใช้งาน:

var x1 = 0 ; // ตัวแปรส่วนกลาง เนื่องจากไม่ได้อยู่ในฟังก์ชันใดๆlet x2 = 0 ; // ตัวแปรส่วนกลางเช่นกัน เนื่องจากไม่ได้อยู่ในบล็อกใดๆฟังก์ชันf () { var z = 'foxes' , r = 'birds' ; // ตัวแปรโลคอล 2 ตัวm = 'fish' ; // ตัวแปรโกลบอล เนื่องจากไม่ได้ประกาศไว้ที่ใดมาก่อนฟังก์ชันลูก() { var r = 'monkeys' ; // ตัวแปรนี้เป็นตัวแปรภายในและไม่มีผลต่อตัวแปร r "birds" ของฟังก์ชันแม่z = 'penguins' ; // Closure: ฟังก์ชันลูกสามารถเข้าถึงตัวแปรของฟังก์ชันแม่ได้}twenty = 20 ; // ตัวแปรนี้ถูกประกาศในบรรทัดถัดไป แต่สามารถใช้ได้ทุกที่ในฟังก์ชัน แม้กระทั่งก่อนหน้านั้น ดังเช่นในตัวอย่างนี้var twenty ;child (); return x1 + x2 ; // เราสามารถใช้ x1 และ x2 ได้ที่นี่ เพราะเป็นตัวแปรส่วนกลาง}();console.log ( z ); // บรรทัดนี้จะทำให้เกิดข้อผิดพลาด ReferenceError เนื่องจากค่าของ z ไม่สามารถใช้งานได้อีกต่อไป
for ( let i = 0 ; i < 10 ; i ++ ) console . log ( i ); console . log ( i ); // ทำให้เกิดข้อผิดพลาด ReferenceError: i ไม่ได้ถูกกำหนด
for ( const i = 0 ; i < 10 ; i ++ ) console . log ( i ); // จะเกิดข้อผิดพลาด TypeError: Assignment to constant variablefor ( const i of [ 1 , 2 , 3 ]) console . log ( i ); //จะไม่เกิดข้อยกเว้น i ไม่ได้ถูกกำหนดค่าใหม่ แต่ถูกสร้างขึ้นใหม่ในทุกรอบการวนซ้ำconst pi ; // จะเกิดข้อผิดพลาด SyntaxError: Missing initializer in const declaration

ประเภทข้อมูลพื้นฐาน

ภาษา JavaScript มีชนิดข้อมูลพื้นฐาน 6 ชนิด ได้แก่:

  • Undefined
  • Number
  • BigInt
  • String
  • Boolean
  • Symbol

ประเภทข้อมูลพื้นฐานบางประเภทยังมีชุดค่าที่มีชื่อกำกับไว้เพื่อแสดงขอบเขตของประเภทข้อมูลนั้นๆ ค่าที่มีชื่อกำกับเหล่านี้จะได้รับการอธิบายในส่วนที่เกี่ยวข้องด้านล่าง

ไม่ได้กำหนด

ค่า"undefined" จะถูกกำหนดให้กับ ตัวแปรที่ยังไม่ได้เริ่มต้นทั้งหมดและจะถูกส่งกลับเมื่อตรวจสอบคุณสมบัติของอ็อบเจ็กต์ที่ไม่มีอยู่จริง ในบริบทของค่าบูลีน ค่า undefined จะถือว่าเป็นค่าเท็จ

หมายเหตุ: ค่า undefined ถือเป็นชนิดข้อมูลพื้นฐานแท้จริง เว้นแต่จะมีการแปลงอย่างชัดเจน ค่า undefined อาจแสดงพฤติกรรมที่ไม่คาดคิดเมื่อเปรียบเทียบกับชนิดข้อมูลอื่น ๆ ที่ประเมินค่าเป็น false ในบริบทเชิงตรรกะ

let test ; // ตัวแปรถูกประกาศแล้ว แต่ยังไม่ได้กำหนดค่า ... // ... ตั้งค่าเป็น undefined const testObj = {}; console.log(test ) ; // ตัวแปรtest มีอยู่แต่ค่าไม่ได้ ... // ... ถูกกำหนด แสดง เป็นundefined console.log ( testObj.myProp ); // testObj มีอยู่ แต่คุณสมบัติไม่มี ... // ... แสดงเป็น undefined console.log ( undefined == null ); // ไม่บังคับใช้ประเภทในระหว่างการตรวจสอบ แสดงเป็น true console.log ( undefined === null ); // บังคับใช้ ประเภทในระหว่าง การตรวจ สอบ แสดง เป็นfalse

หมายเหตุ: ไม่มีตัวอักษรในภาษาที่ใช้แทนคำว่า undefined โดยตรง ดังนั้นจึงไม่ใช่วิธีที่เชื่อถือได้ 100% ในการตรวจสอบว่าตัวแปรนั้นเป็น undefined หรือไม่ เพราะในเวอร์ชันก่อน ECMAScript 5 การเขียนค่า undefined เป็นสิ่งที่ถูกต้องตามกฎหมายวิธีที่เชื่อถือได้มากกว่าคือการเปรียบเทียบโดยใช้ ` undefined` (x===undefined)varundefined="I'm defined now";(typeofx==='undefined')

ฟังก์ชันลักษณะนี้จะไม่ทำงานตามที่คาดหวัง:

ฟังก์ชันisUndefined ( x ) { let u ; return x === u ; } // แบบนี้... ฟังก์ชันisUndefined ( x ) { return x === void 0 ; } // ... หรือแบบที่สองฟังก์ชันisUndefined ( x ) { return ( typeof x ) === "undefined" ; } // ... หรือแบบที่สาม

ในกรณีนี้ การเรียกใช้ฟังก์ชันisUndefined(my_var)จะทำให้เกิดข้อผิดพลาด ReferenceErrorหากmy_varเป็นตัวระบุที่ไม่รู้จัก ในขณะที่ การเรียกใช้ฟังก์ชันอื่น จะไม่ ทำให้เกิดข้อผิดพลาดดังกล่าวtypeofmy_var==='undefined'

ตัวเลข

ตัวเลขจะถูกแสดงในรูปแบบเลขฐานสองโดยใช้ค่าทศลอยIEEE 754 แบบดับเบิล แม้ว่ารูปแบบนี้จะให้ความแม่นยำเกือบ 16 หลักสำคัญแต่ก็ไม่สามารถแสดงจำนวนจริงได้อย่างแม่นยำเสมอไป รวมถึงเศษส่วนด้วย

ปัญหานี้เกิดขึ้นเมื่อเปรียบเทียบหรือจัดรูปแบบตัวเลข ตัวอย่างเช่น:

console.log ( 0.2 + 0.1 === 0.3 ); // แสดง ผลเป็น false console.log ( 0.94 - 0.01 ); // แสดงผลเป็น0.9299999999999999

ด้วยเหตุนี้ จึง ควรใช้วิธีการต่างๆ เช่น เมธอดtoFixed() เพื่อปัดเศษตัวเลขทุกครั้งที่มี การจัดรูปแบบตัวเลขสำหรับการแสดงผล

สามารถระบุตัวเลขได้โดยใช้สัญลักษณ์ใดสัญลักษณ์หนึ่งต่อไปนี้:

345 ; // จำนวนเต็ม แม้ว่าจะมีเพียงชนิดข้อมูลตัวเลขเดียวใน JavaScript 34.5 ; // จำนวนทศนิยม3.45e2 ; // จำนวนทศนิยมอีกตัว เทียบเท่ากับ 345 0b1011 ; // จำนวนเต็มไบนารีเท่ากับ 11 0o377 ; // จำนวนเต็มฐานแปดเท่ากับ 255 0xFF ; // จำนวนเต็มฐานสิบหกเท่ากับ 255 ตัวเลขแทนด้วย ... // ... ตัวอักษร AF อาจพิมพ์ใหญ่หรือพิมพ์เล็ก

นอกจากนี้ยังมีตัวคั่นตัวเลข_ (เครื่องหมายขีดล่าง) ซึ่งถูกนำมาใช้ใน ES2021:

// หมายเหตุ: ไวยากรณ์ของวิกิพีเดียยังไม่รองรับตัวคั่นตัวเลข1 _000_000_000 ; // ใช้กับตัวเลขขนาดใหญ่1 _000_000 .5 ; // รองรับทศนิยม1 _000e1_000 ; // รองรับเลขยกกำลัง// รองรับเลขฐานสอง ฐานแปด และฐานสิบหก0b0000 _0000_0101_1011 ; 0o0001 _3520_0237_1327 ; 0xFFFF _FFFF_FFFF_FFFE ;// แต่ผู้ใช้ไม่สามารถใช้ตัวคั่นเหล่านี้ติดกับส่วนที่เป็นตัวเลขที่ไม่ใช่ตัวเลข หรือที่ต้นหรือท้ายของตัวเลขได้_12 ; // ตัวแปรไม่ได้ถูกกำหนด (เครื่องหมายขีดล่างทำให้เป็นตัวระบุตัวแปร) 12 _ ; // ข้อผิดพลาดทางไวยากรณ์ (ไม่สามารถอยู่ท้ายตัวเลขได้) 12 _ .0 ; // ข้อผิดพลาดทางไวยากรณ์ (การวางตัวคั่นไว้ข้างจุดทศนิยมไม่สมเหตุสมผล) 12. _0 ; // ข้อผิดพลาดทางไวยากรณ์12 e_6 ; // ข้อผิดพลาดทางไวยากรณ์ (อยู่ติดกับ "e" ซึ่งไม่ใช่ตัวเลข การวางตัวคั่นไว้ที่ต้นไม่สมเหตุสมผล) 1000 ____0000 ; // ข้อผิดพลาดทางไวยากรณ์ (อยู่ติดกับ "_" ซึ่งไม่ใช่ตัวเลข อนุญาตให้ใช้ตัวคั่นได้เพียงครั้งละ 1 ตัวเท่านั้น)

ค่า+∞ , −∞และNaN (ไม่ใช่ตัวเลข) ของชนิดข้อมูลตัวเลข สามารถหาได้จากนิพจน์โปรแกรมสองแบบ:

อนันต์; // อนันต์บวก (อนันต์ลบได้จาก -Infinity เป็นต้น) NaN ; // ค่าที่ไม่ใช่ตัวเลข ซึ่งจะถูกส่งคืนเป็นค่าผิดพลาดใน ... // ... การแปลงสตริงเป็นตัวเลข

อนันต์และ NaN เป็นตัวเลข:

typeof Infinity ; // คืนค่าเป็น "number" typeof NaN ; // คืนค่าเป็น "number"

ค่าพิเศษทั้งสามนี้สอดคล้องกันและมีพฤติกรรมตามที่มาตรฐาน IEEE-754ระบุไว้

สามารถใช้ตัวสร้างประเภทข้อมูล Number (ซึ่งใช้เป็นฟังก์ชัน) หรือเครื่องหมาย + หรือ - เพื่อทำการแปลงค่าตัวเลขโดยตรงได้:

const myString = "123.456" ; const myNumber1 = Number ( myString ); const myNumber2 = + myString ;

เมื่อใช้เป็นตัวสร้าง จะมีการสร้างอ็อบเจ็กต์ ห่อ หุ้มตัวเลข ขึ้นมา (แม้ว่าจะมีประโยชน์เพียงเล็กน้อยก็ตาม):

const myNumericWrapper = new Number ( 123.456 );

อย่างไรก็ตาม NaN ไม่เท่ากับตัวมันเอง:

const น่าน= น่าน; คอนโซลเข้าสู่ระบบ( น่าน== น่าน); // คอนโซลเท็จเข้าสู่ระบบ( น่าน=== น่าน); // คอนโซลเท็จเข้าสู่ระบบ( น่าน!== น่าน); // คอนโซลที่ แท้จริง เข้าสู่ระบบ( แนน!== แนน); // จริง// ผู้ใช้สามารถใช้เมธอด isNaN เพื่อตรวจสอบค่า NaN ได้console.log ( isNaN ( " converted to NaN" ) ); // true console.log ( isNaN ( NaN ) ) ; // true console.log ( Number.isNaN ( " not converted " )); // false console.log( Number.isNaN ( NaN ) ) ; // true

บิ๊กอินท์

ใน JavaScript ตัวเลขปกติจะถูกแทนด้วยชนิดข้อมูลจุดลอยตัว IEEE 754 ซึ่งหมายความว่าจำนวนเต็มสามารถจัดเก็บได้อย่างปลอดภัยก็ต่อเมื่อค่าอยู่ระหว่างNumber.MIN_SAFE_INTEGERและNumber.MAX_SAFE_INTEGERเท่านั้น[ 10 ]ในทางกลับกัน BigInts แทนจำนวนเต็มขนาดใดก็ได้ ทำให้โปรแกรมเมอร์สามารถจัดเก็บจำนวนเต็มที่สูงหรือต่ำเกินกว่าที่จะแสดงด้วยรูปแบบ IEEE 754 ได้[ 11 ]

มีสองวิธีในการประกาศค่า BigInt nสามารถเพิ่มเข้าไปในจำนวนเต็ม หรือBigIntสามารถใช้ฟังก์ชันได้: [ 11 ]

const a = 12345n ; // สร้างตัวแปรและเก็บค่า BigInt เท่ากับ 12345 const b = BigInt ( 12345 );

สตริง

สตริงใน JavaScript คือลำดับของอักขระ ใน JavaScript สามารถสร้างสตริงได้โดยตรง (เป็นลิเทอรัล) โดยการวางลำดับของอักขระไว้ระหว่างเครื่องหมายคำพูดคู่ ( )"หรือ'เครื่องหมายคำพูดเดี่ยว ( ) สตริงดังกล่าวต้องเขียนในบรรทัดเดียว แต่อาจมีอักขระขึ้นบรรทัดใหม่ที่ถูกหลีกเลี่ยง (เช่น\n) มาตรฐาน JavaScript อนุญาตให้ใช้ อักขระ แบ็กควอต ( `, หรือที่รู้จักกันในชื่อ grave accent หรือ backtick) เพื่ออ้างอิงสตริงลิเทอรัลหลายบรรทัด รวมถึงนิพจน์ที่ฝังอยู่โดยใช้ไวยากรณ์[ 12 ]${expression}

const greeting = "สวัสดีชาวโลก!" ; const anotherGreeting = 'สวัสดีชาวโลก' ; const aMultilineGreeting = `ด้วยความเคารพอย่างสูง, จอห์น โด' ;// เทมเพลตลิเทอรัลจะแปลงประเภทของนิพจน์ที่ประเมินแล้วและแทรกเข้าไปในสตริงconst templateLiteral = `นี่คือสิ่งที่เก็บไว้ใน anotherGreeting: ${ anotherGreeting } .` ; console . log ( templateLiteral ); // 'นี่คือสิ่งที่เก็บไว้ใน anotherGreeting: 'สวัสดีชาวโลก' console . log ( `คุณมีอายุ${ Math . floor ( age )=> 18 ? "ได้รับอนุญาต" : "ไม่ได้รับอนุญาต" } เพื่อดูเว็บเพจนี้` );

สามารถเข้าถึงอักขระแต่ละตัวภายในสตริงได้โดยใช้ เมธอด charAt (ซึ่งมีอยู่ในString.prototype ) นี่เป็นวิธีที่แนะนำเมื่อต้องการเข้าถึงอักขระแต่ละตัวภายในสตริง เนื่องจากใช้งานได้ในเบราว์เซอร์ที่ไม่ทันสมัยด้วยเช่นกัน:

const h = greeting.charAt ( 0 ) ;

ในเบราว์เซอร์สมัยใหม่ สามารถเข้าถึงอักขระแต่ละตัวภายในสตริงได้ (ในฐานะสตริงที่มีเพียงอักขระเดียว) โดยใช้สัญลักษณ์เดียวกับอาร์เรย์:

const h = greeting [ 0 ];

อย่างไรก็ตาม สตริงใน JavaScript นั้นไม่สามารถเปลี่ยนแปลงได้ :

greeting [ 0 ] = "H" ; // ล้มเหลว

การใช้ตัวดำเนินการความเท่าเทียมกัน ("==") กับสตริงสองสตริงจะคืนค่าเป็นจริง หากสตริงทั้งสองมีเนื้อหาเหมือนกัน ซึ่งหมายความว่า มีความยาวเท่ากันและประกอบด้วยลำดับตัวอักษรเดียวกัน (ตัวพิมพ์ใหญ่เล็กมีความสำคัญสำหรับตัวอักษร) ดังนั้น:

const x = "World" ; const compare1 = ( "Hello, " + x == "Hello, World" ); // ในที่นี้ compare1 มีค่าเป็น true const compare2 = ( "Hello, " + x == "hello, World" ); // ในที่นี้ compare2 มีค่าเป็น ... // ... false เนื่องจาก ... // ... ตัวอักษรตัวแรก ... // ... ของตัวถูกดำเนินการทั้งสอง ... // ... ไม่ใช่ตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็กเดียวกัน

เครื่องหมายอัญประกาศชนิดเดียวกันไม่สามารถซ้อนกันได้ เว้นแต่จะมี การใส่เครื่องหมาย หลีก (escape ) ไว้

let x = '"Hello, World!" he said.' ; // ถูกต้องx = "" Hello , World ! " he said." ; // ไม่ถูกต้องx = "\"Hello, World!\" he said." ; // ใช้ได้โดยการหลีกเลี่ยง " ด้วย \"

ตัว สร้าง Stringจะสร้างอ็อบเจ็กต์สตริง (อ็อบเจ็กต์ที่ห่อหุ้มสตริง):

const greeting = new String ( "Hello, World!" );

อ็อบเจ็กต์เหล่านี้มี เมธอด valueOfที่ส่งคืนสตริงแบบดั้งเดิมที่ห่อหุ้มอยู่ภายใน:

const s = new String ( "Hello!" ); typeof s ; // เป็น ' object' typeof s.valueOf ( ); // เป็น 'string'

ความเท่าเทียมกันระหว่างอ็อบเจ็กต์ Stringสองตัวจะไม่ทำงานเหมือนกับค่าพื้นฐานของสตริง:

const s1 = new String ( "Hello!" ) ; const s2 = new String ( "Hello!" ) ; s1 == s2 ; // เป็นเท็จ เพราะเป็นอ็อบเจ็กต์ที่แตกต่างกันสองตัวs1.valueOf() == s2.valueOf ( ) ; // เป็นจริง

บูลีน

JavaScriptมีชนิดข้อมูลบูลีน (Boolean ) ที่มี ค่า เป็น trueและfalseตัวดำเนิน การ `typeof`จะคืนค่าเป็นสตริง"boolean"สำหรับชนิดข้อมูลพื้นฐาน เหล่านี้ เมื่อใช้ในบริบทเชิงตรรกะ ค่า0 , -0 , null , NaN , undefinedและสตริงว่าง ( "" ) จะถูกประเมินเป็นfalseเนื่องจากการแปลงชนิดข้อมูล อัตโนมัติ ค่าอื่นๆ ทั้งหมด (ส่วนเติมเต็มของรายการก่อนหน้า) จะถูกประเมินเป็นtrueรวมถึงสตริง"0" , "false"และออบเจ็กต์ใดๆ

การแปลงประเภท

การแปลงประเภทอัตโนมัติโดยตัวดำเนินการเปรียบเทียบความเท่าเทียมกัน ( ==และ!=) สามารถหลีกเลี่ยงได้โดยใช้ตัวดำเนินการเปรียบเทียบที่ตรวจสอบประเภทแล้ว ( ===และ!==)

เมื่อจำเป็นต้องมีการแปลงประเภท JavaScript จะแปลง ตัวดำเนินการ Boolean , Number , StringหรือObjectดังนี้: [ 13 ]

ตัวเลขและสตริง
สตริงจะถูกแปลงเป็นค่าตัวเลข JavaScript พยายามแปลงตัวเลขในสตริงให้เป็นค่าประเภท Number โดยขั้นแรก จะคำนวณหาค่าทางคณิตศาสตร์จากตัวเลขในสตริง จากนั้นจะปัดเศษค่าที่ได้ให้เป็นค่าประเภท Number ที่ใกล้เคียงที่สุด
บูลีน
ถ้าตัวถูกดำเนินการตัวใดตัวหนึ่งเป็นค่าบูลีน ค่าบูลีนนั้นจะถูกแปลงเป็น 1 ถ้าเป็นจริงหรือเป็น 0 ถ้าเป็นเท็จ
วัตถุ
หากมีการเปรียบเทียบอ็อบเจ็กต์กับตัวเลขหรือสตริง JavaScript จะพยายามส่งคืนค่าเริ่มต้นของอ็อบเจ็กต์นั้น โดยจะแปลงอ็อบเจ็กต์เป็นค่าสตริงหรือตัวเลขโดยใช้เมธอด.valueOf()หรือ.toString()ของอ็อบเจ็กต์นั้น หากการแปลงล้มเหลว จะเกิดข้อผิดพลาดขณะรันไทม์

การแปลงประเภทบูลีน

Douglas Crockfordสนับสนุนคำว่า "truthy" และ "falsy" เพื่ออธิบายว่าค่าของประเภทต่างๆ มีพฤติกรรมอย่างไรเมื่อประเมินในบริบทเชิงตรรกะ โดยเฉพาะอย่างยิ่งในส่วนที่เกี่ยวกับกรณีพิเศษ[ 14 ] ตัวดำเนินการตรรกะแบบไบนารีจะส่งคืนค่าบูลีนใน JavaScript เวอร์ชันแรกๆ แต่ตอนนี้จะส่งคืนค่าตัวถูกดำเนินการตัวใดตัวหนึ่งแทน ตัวถูกดำเนินการด้านซ้ายจะถูกส่งคืน หากสามารถประเมินได้เป็น: เท็จในกรณีของการเชื่อม : ( ) หรือจริงในกรณีของการแยก : ( ); มิฉะนั้นจะส่งคืนตัวถูกดำเนินการด้านขวา การแปลงประเภทอัตโนมัติโดยตัวดำเนินการเปรียบเทียบอาจแตกต่างกันสำหรับกรณีของตัวถูกดำเนินการที่ผสมระหว่างบูลีนและตัวเลขที่เข้ากันได้ (รวมถึงสตริงที่สามารถประเมินเป็นตัวเลขได้ หรือออบเจ็กต์ที่สามารถประเมินเป็นสตริงดังกล่าวได้) เนื่องจากตัวถูกดำเนินการบูลีนจะถูกเปรียบเทียบเป็นค่าตัวเลข นี่อาจเป็นสิ่งที่ไม่คาดคิด สามารถแปลงนิพจน์เป็นค่าบูลีนได้อย่างชัดเจนโดยการใช้ตัวดำเนินการปฏิเสธ เชิงตรรกะซ้ำสองครั้ง : ( !! ) โดยใช้ ฟังก์ชัน Boolean()หรือใช้ตัวดำเนินการเงื่อนไข : ( ) a && ba || bc ? t : f

// การแปลงประเภทอัตโนมัติconsole.log ( true == 2 ); // false... true → 1 !== 2 ← 2 console.log ( false == 2 ) ; // false... false → 0 !== 2 ← 2 console.log(true == 1); // true.... true → 1 === 1 ← 1 console.log( false == 0 ) ; // true .... false 0 === 0 0 console.log ( true == " 2 " ) ; // false ... true → 1 !== 2 ← "2" console.log ( false == " 2" ); // false... false → 0 !== 2 ← "2" console.log ( true == " 1" ); // true .... true → 1 === 1 "1" console.log ( false == "0" ) ; // จริง .... false → 0 === 0 ← "0" console เข้าสู่ระบบ( เท็จ== "" ); // จริง .... เท็จ → 0 === 0 ← "" console เข้าสู่ระบบ( เท็จ== น่าน); // เท็จ... เท็จ → 0 !== น่านconsole.log ( NaN == NaN ); // false...... NaN ไม่เท่ากับอะไรเลย รวมถึง NaN ด้วย// การเปรียบเทียบแบบตรวจสอบประเภท ( ไม่มีการแปลงประเภทและค่า) console.log ( true === 1 ); // false...... ประเภทข้อมูลไม่ตรงกัน// การแปลงประเภทข้อมูลอย่างชัดเจนconsole.log ( true === !! 2 ) ; // true.... ประเภทข้อมูลและค่าตรงกันconsole.log ( true === !! 0 ); // false... ประเภทข้อมูลตรงกัน แต่ค่าต่างกันconsole.log ( 1 ? true : false ); // true.... มีเพียง ± 0 และ NaN เท่านั้นที่เป็นตัวเลข "falsy" console.log ( "0" ? true : false ); // true.... มีเพียงสตริงว่างเท่านั้นที่เป็น "falsy" console.log ( Boolean ( {})); // true.... วัตถุทั้งหมดเป็น " truthy "

ตัวดำเนินการ `new` สามารถใช้สร้างออบเจ็กต์ห่อหุ้มสำหรับค่าบูลีนได้ อย่างไรก็ตาม ตัวดำเนินการ `typeof`ไม่คืนค่าบูลีนสำหรับออบเจ็กต์ห่อหุ้ม แต่จะคืน ค่าออบเจ็กต์ ` object`แทน เนื่องจากออบเจ็กต์ทั้งหมดมีค่าเป็นจริง จึงต้องใช้ วิธีการเช่น`.valueOf() ` หรือ`.toString()`เพื่อดึงค่าที่ห่อหุ้มไว้ สำหรับการแปลงเป็นประเภทบูลีนอย่างชัดเจน Mozilla แนะนำให้ ใช้ฟังก์ชัน `Boolean()` (โดยไม่ต้องใช้`new` ) แทนการใช้ออบเจ็กต์บูลีน

const b = new Boolean ( false ); // อ็อบเจ็กต์ false {} const t = Boolean ( b ); // Boolean true const f = Boolean ( b.valueOf ( )); // Boolean false let n = new Boolean ( b ); // ไม่แนะนำn = new Boolean ( b.valueOf ( ) ); // แนะนำถ้า( 0 || - 0 || "" || null || undefined || b.valueOf () || ! new Boolean () || ! t ) { console.log ( " ไม่เคยเป็นแบบนี้" ) ; } else if ( [] && { } && b && typeof b === "object" && b.toString ( ) === "false" ) { console.log ( " เป็นแบบนี้เสมอ" ); }

เครื่องหมาย

สัญลักษณ์เป็นคุณสมบัติที่นำมาใช้ในES6แต่ละสัญลักษณ์รับประกันว่ามีค่าที่ไม่ซ้ำกัน และสามารถใช้สำหรับการห่อหุ้มได้[ 15 ]

ตัวอย่าง:

let x = Symbol ( 1 ); const y = Symbol ( 1 ); x === y ; // => falseconst symbolObject = {}; const normalObject = {};// เนื่องจาก x และ y มีค่าไม่ซ้ำกัน// จึงสามารถใช้เป็นคีย์ที่ไม่ซ้ำกันในออบเจ็กต์symbolObject [ x ] = 1 ; symbolObject [ y ] = 2 ;symbolObject [ x ]; // => 1 symbolObject [ y ]; // => 2// เมื่อเปรียบเทียบกับปุ่มตัวเลขปกติnormalObject [ 1 ] = 1 ; normalObject [ 1 ] = 2 ; // แทนที่ค่าของ 1normalObject [ 1 ]; // => 2// การเปลี่ยนค่าของ x จะไม่เปลี่ยนคีย์ที่เก็บไว้ในอ็อบเจ็กต์x = Symbol ( 3 ); symbolObject [ x ]; // => ไม่ได้กำหนด// การเปลี่ยน x กลับเป็นค่าเดิมจะสร้าง Symbol ที่ไม่ซ้ำกันอีกอันหนึ่งx = Symbol ( 1 ); symbolObject [ x ]; // => ไม่ได้กำหนด

นอกจากนี้ยังมี สัญลักษณ์ ที่ เป็นที่รู้จักกันดี อีกด้วย

หนึ่งในนั้นคือSymbol.iteratorถ้าสิ่งใดสิ่งหนึ่งใช้งานตามหลักการ นี้ได้ Symbol.iteratorแสดงว่าสิ่งนั้นสามารถวนซ้ำได้:

const x = [ 1 , 2 , 3 , 4 ]; // x เป็นอาร์เรย์x [ Symbol . iterator ] === Array . prototype [ Symbol . iterator ]; // และอาร์เรย์สามารถวนซ้ำได้const xIterator = x [ Symbol.iterator ](); // ฟังก์ชัน [ Symbol.iterator ] ควรให้ iterator สำหรับ x xIterator.next ( ) ; // { value: 1, done: false } xIterator.next ( ) ; // { value: 2 , done: false } xIterator.next ( ); // { value: 3, done: false } xIterator.next (); // { value : 4, done: false } xIterator.next ( ); // { value: undefined, done : true } xIterator.next (); // { value: undefined, done: true }// ลูป for..of จะวนซ้ำค่าโดยอัตโนมัติfor ( const value of x ) { console . log ( value ); // 1 2 3 4 }// เซตก็สามารถวนซ้ำได้เช่นกัน: [ Symbol . iterator ] in Set . prototype ; // truefor ( const value of new Set ([ 'apple' , 'orange' ])) { console . log ( value ); // "apple" "orange" }

วัตถุพื้นฐาน

ภาษา JavaScript มีอ็อบเจ็กต์ พื้นฐานอยู่จำนวนหนึ่ง อ็อบเจ็กต์พื้นฐานของ JavaScript ถือเป็นส่วนหนึ่งของข้อกำหนดเฉพาะของ JavaScript ไม่ว่าสภาพแวดล้อมของ JavaScript จะเป็นอย่างไร อ็อบเจ็กต์ชุดนี้ควรพร้อมใช้งานเสมอ

อาร์เรย์

อาร์เรย์ ( Array)เป็นอ็อบเจ็กต์ใน JavaScript ที่สร้างต้นแบบมาจากArrayคอนสตรัคเตอร์ (Constructor) โดยเฉพาะ ซึ่งออกแบบมาเพื่อจัดเก็บค่าข้อมูลโดยใช้คีย์ที่เป็นจำนวนเต็ม อาร์เรย์นั้นแตกต่างจากอ็อบเจ็กต์พื้นฐานตรงที่มีเมธอดและคุณสมบัติเพื่อช่วยให้โปรแกรมเมอร์ทำงานประจำได้ง่ายขึ้น (เช่น การค้นหาแบบอินเทอร์เฟส (Integer) และการค้นหาแบบอินเทอร์เฟส ( joinInteger slice) push)

เช่นเดียวกับในภาษาตระกูล Cอาร์เรย์ใช้ระบบการจัดทำดัชนีแบบเริ่มต้นที่ศูนย์: ค่าที่ถูกแทรกเข้าไปในอาร์เรย์ว่างโดยใช้pushวิธีการดังกล่าว จะครอบครองดัชนีลำดับที่ 0 ของอาร์เรย์

const myArray = []; // ชี้ตัวแปร myArray ไปยังอาร์เรย์ว่างที่สร้างขึ้นใหม่ ... // myArray.push ( " hello World" ); // เติมดัชนีว่างถัดไป ในกรณีนี้คือ 0 console.log ( myArray [ 0 ] ); // เทียบเท่ากับ console.log ("hello World") ;

อาร์เรย์มีlengthคุณสมบัติหนึ่งที่รับประกันว่าจะมีค่ามากกว่าดัชนีจำนวนเต็มที่ใหญ่ที่สุดที่ใช้ในอาร์เรย์เสมอ ค่านี้จะได้รับการอัปเดตโดยอัตโนมัติหากมีการสร้างคุณสมบัติที่มีดัชนีที่มากกว่าเดิม การเขียนตัวเลขที่เล็กกว่าลงในlengthคุณสมบัติจะลบดัชนีที่ใหญ่กว่าออกไป

Arrayสามารถเข้าถึง องค์ประกอบของ s ได้โดยใช้สัญกรณ์การเข้าถึงคุณสมบัติของวัตถุตามปกติ:

myArray [ 1 ]; // รายการที่ 2 ใน myArray myArray [ "1" ];

สองอย่างข้างต้นนั้นเทียบเท่ากัน ไม่สามารถใช้สัญลักษณ์ "จุด" หรือสตริงที่มีการแสดงตัวเลขในรูปแบบอื่นได้:

myArray.1 ; // ข้อผิดพลาดทางไวยากรณ์myArray [ "01" ]; // ไม่เหมือนกับ myArray[1]

การประกาศอาร์เรย์สามารถใช้ได้ทั้งค่าArrayคงที่หรือArrayตัวสร้าง:

ให้myArray ;// ค่าคงที่ของอาร์เรย์myArray = [ 1 , 2 ]; // ความยาว 2 myArray = [ 1 , 2 ,]; // อาร์เรย์เดียวกัน - ผู้ใช้สามารถเพิ่มเครื่องหมายจุลภาคที่ท้ายได้ด้วย// นอกจากนี้ยังสามารถเว้นการเติมข้อมูลในบางส่วนของอาร์เรย์ได้myArray = [ 0 , 1 , /* ช่องว่าง */ , /* ช่องว่าง */ , 4 , 5 ]; // ความยาว 6 myArray = [ 0 , 1 , /* ช่องว่าง */ , /* ช่องว่าง */ , 4 , 5 ,]; // อาร์เรย์เดียวกันmyArray = [ 0 , 1 , /* ช่องว่าง */ , /* ช่องว่าง */ , 4 , 5 , /* ช่องว่าง */ ,]; // ความยาว 7// ด้วยคอนสตรัคเตอร์myArray = new Array ( 0 , 1 , 2 , 3 , 4 , 5 ); // ความยาว 6 myArray = new Array ( 365 ); // อาร์เรย์ว่างที่มีความยาว 365

อาร์เรย์ถูกสร้างขึ้นโดยใช้หน่วยความจำเฉพาะสำหรับองค์ประกอบที่กำหนดไว้เท่านั้น เรียกว่า " อาร์เรย์แบบเบาบาง " การตั้งค่าให้ใช้พื้นที่สำหรับองค์ประกอบสองตัวนี้เท่านั้น เช่นเดียวกับวัตถุอื่นๆ ขนาดหน่วยความ จำของอาร์เรย์จะยังคงแสดงเป็น 58 ความยาวสูงสุดของอาร์เรย์คือ 4,294,967,295 ซึ่งตรงกับเลขฐานสอง 32 บิต (11111111111111111111111111111111) 2myArray[10]='someThing'myArray[57]='somethingOther'length

เราสามารถใช้ตัวอักษรประกาศวัตถุเพื่อสร้างวัตถุที่มีพฤติกรรมคล้ายกับอาร์เรย์แบบเชื่อมโยงในภาษาโปรแกรมอื่นๆ ได้:

const dog = { color : "brown" , size : "large" }; dog [ "color" ]; // ผลลัพธ์คือ "brown" dog . color ; // ผลลัพธ์ก็คือ "brown" เช่นกัน

เราสามารถใช้ตัวอักษรประกาศออบเจ็กต์และอาร์เรย์เพื่อสร้างอาร์เรย์แบบเชื่อมโยง อาร์เรย์หลายมิติ หรือทั้งสองอย่างได้อย่างรวดเร็ว (ในทางเทคนิคแล้ว JavaScript ไม่รองรับอาร์เรย์หลายมิติ แต่เราสามารถจำลองได้โดยใช้อาร์เรย์ของอาร์เรย์)

const cats = [{ color : "brown" , size : "large" }, { color : "black" , size : "small" }]; cats [ 0 ][ "size" ]; // ผลลัพธ์คือ "large"const dogs = { rover : { color : "brown" , size : "large" }, spot : { color : "black" , size : "small" }}; dogs [ "spot" ][ "size" ]; // ผลลัพธ์คือ "small" dogs . rover . color ; // ผลลัพธ์คือ "brown"

วันที่

อ็อบเจ็กต์นี้Dateเก็บค่าการนับมิลลิวินาทีแบบมีเครื่องหมาย โดยที่ศูนย์แทนวันที่ 1 มกราคม 1970 เวลา 00:00:00 UT และช่วงค่าคือ ±10.8 วันมีหลายวิธีในการส่งอาร์กิวเมนต์ไปยังDateคอนสตรัคเตอร์ โปรดทราบว่าเดือนเริ่มต้นจากศูนย์

new Date (); // สร้างอินสแตนซ์ Date ใหม่ที่แสดงถึงเวลา/วันที่ปัจจุบันnew Date ( 2010 , 2 , 1 ); // สร้างอินสแตนซ์ Date ใหม่ที่แสดงถึงวันที่ 1 มีนาคม 2010 เวลา 00:00:00 new Date ( 2010 , 2 , 1 , 14 , 25 , 30 ); // สร้างอินสแตนซ์ Date ใหม่ที่แสดงถึงวันที่ 1 มีนาคม 2010 เวลา 14:25:30 new Date ( "2010-3-1 14:25:30" ); // สร้างอินสแตนซ์ Date ใหม่จากสตริง

มีการระบุวิธีการแยกฟิลด์ รวมถึงข้อมูลที่เป็นประโยชน์ดังนี้toString:

const d = new Date ( 2010 , 2 , 1 , 14 , 25 , 30 ); // 2010-มี.ค.-01 14:25:30;// แสดง ผล ' 2010-3-1 14:25:30 ' : console.log ( d.getFullYear () + '-' + ( d.getMonth () + 1 ) + ' - ' + d.getDate ( ) + ' ' + d.getHours ( ) + ' : ' + d.getMinutes ( ) + ':' + d.getSeconds ( ) );// เมธอด toString ในตัวจะส่งคืน ค่าประมาณ 'Mon 1 March, 2010 14:25:30 GMT-0500 (EST)': console.log ( d ) ;

ข้อผิดพลาด

สามารถสร้างข้อความแสดงข้อผิดพลาดแบบกำหนดเองได้โดยใช้Errorคลาส:

throw new Error ( "เกิดข้อผิดพลาดบางอย่าง" );

ข้อผิดพลาดเหล่านี้สามารถดักจับได้โดยใช้บล็อก try...catch...finally ตามที่อธิบายไว้ในส่วนเกี่ยวกับการ จัดการข้อผิดพลาด

คณิตศาสตร์

อ็อบเจ็กต์Mathประกอบด้วยค่าคงที่ทางคณิตศาสตร์ต่างๆ (เช่นπ ) และฟังก์ชัน (เช่น โคไซน์) (โปรดทราบว่า อ็อบเจ็กต์ Mathไม่มีคอนสตรัคเตอร์ ต่างจากArrayหรือDate เมธอดทั้งหมดของมันเป็น "static" นั่นคือเมธอดของ "คลาส " ) ฟังก์ชันตรีโกโนเมตริกทั้งหมดใช้มุมที่แสดงในหน่วยเรเดียนไม่ใช่องศาหรือเกรด

ค่าคงที่บางส่วนที่อยู่ในออบเจ็กต์ Math
คุณสมบัติค่าที่ส่งคืนจะถูกปัดเศษเป็น 5 หลักคำอธิบาย
คณิตศาสตร์ E2.7183e : ฐานลอการิทึมธรรมชาติ
คณิตศาสตร์ LN20.69315ลอการิทึมธรรมชาติของ 2
คณิตศาสตร์ LN102.3026ลอการิทึมธรรมชาติของ 10
คณิตศาสตร์.LOG2E1.4427ลอการิทึมฐาน 2 ของe
คณิตศาสตร์.LOG10E0.43429ลอการิทึมฐาน 10 ของe
คณิตศาสตร์.พีไอ3.14159π : เส้นรอบวง/เส้นผ่านศูนย์กลางของวงกลม
คณิตศาสตร์.SQRT1_20.70711รากที่สองของ ½
คณิตศาสตร์.SQRT21.4142รากที่สองของ 2
เมธอดของออบเจ็กต์คณิตศาสตร์
ตัวอย่างค่าที่ส่งคืนจะถูกปัดเศษเป็น 5 หลักคำอธิบาย
คณิตศาสตร์.abs(-2.3)2.3ค่าสัมบูรณ์
คณิตศาสตร์.acos(คณิตศาสตร์.SQRT1_2)0.78540  เรเดียน = 45°อาร์คโคซีน
Math.asin(Math.SQRT1_2)0.78540 เรเดียน = 45°อาร์คซีน
คณิตศาสตร์.atan(1)0.78540 เรเดียน = 45°ครึ่งวงกลมอาร์คแทนเจนต์ ( ⁠ ⁠ถึง⁠ ⁠ )
Math.atan2(-3.7, -3.7)−2.3562 เรเดียน =−135°อาร์คแทนเจนต์ของวงกลมทั้งหมด ( ⁠ ⁠ถึง⁠ ⁠ )
คณิตศาสตร์.ceil(1.1)2เพดาน: ปัดขึ้นเป็นจำนวนเต็มที่เล็กที่สุดที่มากกว่าหรือเท่ากับค่าที่กำหนด
คณิตศาสตร์.cos(คณิตศาสตร์.PI/4)0.70711โคไซน์
คณิตศาสตร์.exp(1)2.7183ฟังก์ชันเลขชี้กำลัง : eยกกำลังนี้
คณิตศาสตร์.floor(1.9)1Floor: ปัดลงให้เป็นจำนวนเต็มที่มากที่สุด ≤ ค่าที่ป้อนเข้าไป
แมธ.ล็อก(แมธ.อี)1ลอการิทึมธรรมชาติ ฐานe
คณิตศาสตร์สูงสุด(1, -2)1ค่าสูงสุด: (x > y) ? x : y
คณิตศาสตร์.min(1, -2)−2ค่าต่ำสุด: (x < y) ? x : y
Math.pow(-3, 2)9การยกกำลัง (ยกกำลังด้วย): Math.pow(x, y)ให้ผลลัพธ์เป็น x y
สุ่มคณิตศาสตร์()เช่น 0.17068เลข สุ่มเทียมระหว่าง 0 (รวม 0 ด้วย) และ 1 (ไม่รวม 1 ด้วย)
คณิตศาสตร์รอบ(1.5)2ปัดเศษให้เป็นจำนวนเต็มที่ใกล้ที่สุด เศษส่วนครึ่งหนึ่งจะปัดขึ้น (เช่น 1.5 ปัดเป็น 2)
คณิตศาสตร์.sin(คณิตศาสตร์.PI/4)0.70711ไซน์
คณิตศาสตร์.sqrt(49)7รากที่สอง
คณิตศาสตร์แทน(คณิตศาสตร์ PI/4)1แทนเจนต์

นิพจน์ปกติ

/expression/ . test ( string ); // ส่งคืนค่าบูลีน"string" . search ( /expression/ ); // ส่งคืนหมายเลขตำแหน่ง"string" . replace ( /expression/ , replacement );// นี่คือตัวอย่างบางส่วนถ้า( /Tom/ . test ( "My name is Tom" )) console . log ( "Hello Tom!" ); console . log ( "My name is Tom" . search ( /Tom/ )); // == 11 (ตัวอักษรก่อน Tom) console . log ( "My name is Tom" . replace ( /Tom/ , "John" )); // == "My name is John"

คลาสตัวละคร

// \d - ตัวเลข// \D - ไม่ใช่ตัวเลข// \s - ช่องว่าง// \S - ไม่ใช่ช่องว่าง// \w - อักขระคำ// \W - ไม่ใช่อักขระคำ// [ ] - หนึ่งใน// [^] - ไม่ใช่หนึ่งใน// - - ช่วงถ้า( /\d/ . test ( '0' )) console . log ( 'Digit' ); ถ้า( /[0-9]/ . test ( '6' )) console . log ( 'Digit' ); ถ้า( /[13579]/ . test ( '1' )) console . log ( 'Odd number' ); ถ้า( /\S\S\s\S\S\S\S/ . test ( 'My name' )) console . log ( 'Format OK' ); ถ้า( /\w\w\w/ . test ( 'Tom' )) console . log ( 'Hello Tom' ); ถ้า( /[a-zA-Z]/ . test ( 'B' )) console . log ( 'Letter' );

การจับคู่ตัวละคร

// A...Z a...z 0...9 - ตัวอักษรและตัวเลข// \u0000...\uFFFF - เลขฐานสิบหกยูนิโค้ด// \x00...\xFF - เลขฐานสิบหก ASCII // \t - แท็บ// \n - ขึ้นบรรทัดใหม่// \r - CR // . - อักขระใดๆ// | - หรือถ้า( /Tm/ . test ( 'Tom' )) console . log ( 'Hi Tom, Tam or Tim' ); ถ้า( /A|B/ . test ( "A" )) console . log ( 'A or B' );

เครื่องทวนสัญญาณ

// ? - ตรงกัน 0 หรือ 1 รายการ// * - ตรงกัน 0 รายการขึ้นไป// + - ตรงกัน 1 รายการขึ้นไป// {n} - ตรงกับ n พอดี // {n,} - ตรงกับ n รายการ ขึ้นไป // {0,n} - ตรงกับ n รายการหรือน้อยกว่า// {n,m} - อยู่ในช่วง n ถึง mถ้า( /ab?c/ . test ( "ac" )) console . log ( "OK" ); // ตรงกัน: "ac", "abc" ถ้า( /ab*c/ . test ( "ac" )) console . log ( "OK" ); // ตรงกัน: "ac", "abc", "abbc", "abbbc" เป็นต้นถ้า( /ab+c/ . test ( "abc" )) console . log ( "OK" ); // ตรงกัน: "abc", "abbc", "abbbc" เป็นต้นถ้า( /ab{3}c/ . test ( "abbbc" )) console . log ( "OK" ); // ตรงกัน: "abbbc" ถ้า( /ab{3,}c/ . test ( "abbbc" )) console . log ( "OK" ); // จับคู่: "abbbc", "abbbbc", "abbbbbc" ฯลฯif ( /ab { 1,3}c/ . test ( "abc" )) console เข้าสู่ระบบ( "ตกลง" ); // จับคู่: "abc", "abbc", "abbbc"

สมอเรือ

// ^ - สตริงขึ้นต้นด้วย// $ - สตริงลงท้ายด้วยถ้า( /^My/ . test ( "My name is Tom" )) console . log ( "Hi!" ); ถ้า( /Tom$/ . test ( "My name is Tom" )) console . log ( "Hi Tom!" );

นิพจน์ย่อย

// ( ) - จัดกลุ่มอักขระถ้า( /water(mark)?/ . test ( "watermark" )) console . log ( "นี่คือน้ำ!" ); // จับคู่: "water", "watermark", ถ้า( /(Tom)|(John)/ . test ( "John" )) console . log ( "สวัสดี Tom หรือ John!" );

ธง

// /g - ทั่วโลก// /i - ไม่สนใจตัวพิมพ์ใหญ่/พิมพ์เล็ก// /m - อนุญาตให้การจับคู่ครอบคลุมหลายบรรทัดconsole.log ( "hi tom!" . replace ( " /Tom/i" , "John" )); // == "hi John!" console.log ( " ratatam " .replace ( " /ta/" , " tu" )); // == "ratutam" console.log ( "ratatam" .replace ( " /ta/g" , " tu " )); // == "ratutum"

วิธีการขั้นสูง

my_array = my_string.split ( my_delimiter ); // ตัวอย่างmy_array = "dog,cat,cow" .split ( "," ) ; // my_array==["dog " ,"cat", " cow"];my_array = my_string.match ( my_expression ); // ตัวอย่างmy_array = "We start at 11:30, 12:15 and 16:45" .match ( / \d\d:\d\d/g ) ; // my_array==["11:30","12:15","16:45"];

การจับภาพกลุ่ม

const myRe = /(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})/ ; const results = myRe . exec ( "วันที่และเวลาคือ 2009-09-08 09:37:08." ); if ( results ) { console . log ( "ตรงกัน: " + results [ 0 ]); // การจับคู่ทั้งหมดconst my_date = results [ 1 ]; // กลุ่มแรก == "2009-09-08" const my_time = results [ 2 ]; // กลุ่มที่สอง == "09:37:08" console . log ( `เวลา${ my_time } ในวันที่${ my_date } ` ); } else console . log ( "ไม่พบวันที่ที่ถูกต้อง!" );

การทำงาน

ทุกฟังก์ชันใน JavaScript เป็นอินสแตนซ์ของFunctionคอนสตรัคเตอร์:

// x, y คืออาร์กิวเมนต์ 'return x + y' คือส่วนเนื้อหาของฟังก์ชัน ซึ่งเป็นส่วนสุดท้ายในรายการอาร์กิวเมนต์const add = new Function ( 'x' , 'y' , 'return x + y' ); add ( 1 , 2 ); // => 3

ฟังก์ชันการบวกข้างต้นสามารถกำหนดได้โดยใช้การแสดงฟังก์ชันเช่นกัน:

const add = function ( x , y ) { return x + y ; }; add ( 1 , 2 ); // => 3

ใน ES6 ได้มีการเพิ่มไวยากรณ์ฟังก์ชันลูกศร ซึ่งทำให้ฟังก์ชันที่ส่งค่ากลับมีความกระชับมากขึ้น นอกจากนี้ ฟังก์ชันลูกศรยังคงรักษาคุณสมบัติthisของอ็อบเจ็กต์ส่วนกลางไว้ แทนที่จะสืบทอดคุณสมบัติจากตำแหน่งที่เรียกใช้หรือสิ่งที่ถูกเรียกใช้ ซึ่งแตกต่างจากfunction() {}นิพจน์

const add = ( x , y ) => { return x + y ;}; // สามารถส่งค่ากลับโดยปริยายได้ (เช่น ไม่จำเป็นต้องใช้คำสั่ง return) const addImplicit = ( x , y ) => x + y ;add ( 1 , 2 ); // => 3 addImplicit ( 1 , 2 ) // => 3

สำหรับฟังก์ชันที่จำเป็นต้องยกขึ้น (hoisted) จะมีนิพจน์แยกต่างหาก:

ฟังก์ชันadd ( x , y ) { return x + y ; } add ( 1 , 2 ); // => 3

การ Hoisting ช่วยให้ผู้ใช้สามารถใช้ฟังก์ชันได้ก่อนที่จะมีการ "ประกาศ" ฟังก์ชันนั้นอย่างเป็นทางการ:

add ( 1 , 2 ); // => 3 ไม่ใช่ ReferenceError ฟังก์ชันadd ( x , y ) { return x + y ; }

อินสแตนซ์ของฟังก์ชันประกอบด้วยคุณสมบัติและเมธอด

ฟังก์ชันลบ( x , y ) { ส่งคืนค่าx - y ; }console.log ( subtract.length ) ; // = > 2 , จำนวนอาร์กิวเมนต์ของฟังก์ชันconsole.log ( subtract.toString ( ) ) ;/* "ฟังก์ชันลบ (x, y) {  ส่งคืนค่า x - y; }" */

ผู้ปฏิบัติงาน

ตัวดำเนินการ '+' มีการใช้งานหลายรูปแบบ : ใช้สำหรับการเชื่อมต่อสตริงและการบวกทางคณิตศาสตร์ ซึ่งอาจก่อให้เกิดปัญหาหากเผลอผสมสตริงและตัวเลขเข้าด้วยกัน นอกจากนี้ ในฐานะตัวดำเนินการเอกภาค มันสามารถแปลงสตริงตัวเลขให้เป็นตัวเลขได้

// รวม สตริง2 สตริงเข้าด้วยกันconsole.log ( ' He' + 'llo' ); // แสดงผล Hello// บวกเลขสองจำนวนconsole.log ( 2 + 6 ) ; // แสดงผล 8// การบวกตัวเลขและสตริงจะส่งผลให้เกิดการต่อกัน (จากซ้ายไปขวา) console.log( 2 + ' 2 ' ) ; // แสดง ผล22 console.log ( '$' + 3 + 4 ); // แสดงผล $34 แต่ ผลลัพธ์ที่คาดหวังอาจเป็น $7 console.log ( ' $' + ( 3 + 4 )); // แสดงผล $7 console.log ( 3 + 4 + '7' ); // แสดง ผล77 ตัวเลขยังคงเป็นตัวเลขจนกว่าจะมีการบวกสตริงเข้าไป// แปลงสตริงเป็นตัวเลขโดยใช้ตัวดำเนินการบวกแบบเอกภาคconsole.log ( ' + 2 ' === 2 ); // แสดง ค่าtrue console.log ( ' + Hello' ); // แสดงค่า NaN

ในทำนองเดียวกัน ตัวดำเนินการ '*' ก็มีการใช้งานเกินความจำเป็นเช่นกัน กล่าวคือ สามารถแปลงสตริงเป็นตัวเลขได้

console.log ( 2 + ' 6 ' * 1 ); // แสดง ผล8 console.log ( 3 * ' 7' ); // 21 console.log ( ' 3' * '7' ); // 21 console.log ( ' hello ' * 'world' ); // แสดงผล NaN

เลขคณิต

JavaScript รองรับตัวดำเนินการทางคณิตศาสตร์แบบไบนารี ต่อไปนี้ :

+ส่วนที่เพิ่มเข้าไป
-การลบ
*การคูณ
/การหาร (ส่งคืนค่าทศนิยม)
%โมดูลัส (คืนค่าเศษเหลือ)
**การยกกำลัง

JavaScript รองรับตัวดำเนินการทางคณิตศาสตร์แบบเอกภาค ต่อไปนี้ :

+การแปลงสตริงเป็นตัวเลขแบบเอกภาค
-การปฏิเสธเอกภาค (กลับเครื่องหมาย)
++ค่าเพิ่มขึ้น (อาจเป็นค่านำหน้าหรือค่าต่อท้าย)
--การลดค่า (อาจเป็นคำนำหน้าหรือคำต่อท้าย)
let x = 1 ; console.log ( ++ x ); // x กลายเป็น 2; แสดงผล 2 console.log ( x ++ ) ; // แสดง ผล2; x กลายเป็น 3 console.log ( x ); // x คือ 3 ; แสดงผล 3 console.log ( x-- ) ; // แสดงผล 3 ; x กลายเป็น 2 console.log ( x ) ; // แสดงผล 2; x คือ 2 console.log ( -- x ); // x กลายเป็น 1; แสดงผล 1

ตัวดำเนินการโมดูลัสจะแสดงเศษเหลือหลังจากการหารด้วยตัวหาร หากมีจำนวนลบเข้ามาเกี่ยวข้อง ค่าที่ได้จะขึ้นอยู่กับตัวถูกหาร

const x = 17 ; console.log ( x % 5 ); // แสดงผล2 console.log ( x % 6 ); // แสดงผล 5 console.log ( -x % 5 ); // แสดง ผล-2 console.log ( -x % -5 ) ; // แสดง ผล-2 console.log ( x % -5 ) ; // แสดงผล2

เพื่อให้ได้ผลลัพธ์เป็นจำนวนที่ไม่ติดลบเสมอ ผู้ใช้สามารถเพิ่มค่าโมดูลัสกลับเข้าไปใหม่และใช้ตัวดำเนินการโมดูลัสอีกครั้งได้:

const x = 17 ; console.log ( ( - x % 5 + 5 ) % 5 ); // แสดงผล 3

ผู้ใช้ยังสามารถทำสิ่งต่อไปนี้ได้:

const x = 17 ; console.log ( Math.abs ( -x % 5 ) ) ; // also 3

งานที่มอบหมาย

=กำหนด
+=เพิ่มและกำหนด
-=ลบและกำหนด
*=คูณและกำหนด
/=แบ่งและจัดสรร
%=โมดูลัสและการกำหนดค่า
**=การยกกำลังและการกำหนดค่า

การกำหนดประเภทพื้นฐาน

let x = 9 ; x += 1 ; console . log ( x ); // แสดงผล: 10 x *= 30 ; console . log ( x ); // แสดงผล: 300 x /= 6 ; console . log ( x ); // แสดงผล: 50 x -= 3 ; console . log ( x ); // แสดงผล: 47 x %= 7 ; console . log ( x ); // แสดงผล: 5

การกำหนดประเภทของวัตถุ

/** * เพื่อเรียนรู้เกี่ยวกับอ็อบเจ็กต์ใน JavaScript... */ const object_1 = { a : 1 }; // กำหนดค่าอ้างอิงของอ็อบเจ็กต์ที่สร้างขึ้นใหม่ให้กับ object_1 let object_2 = { a : 0 }; let object_3 = object_2 ; // object_3 อ้างอิงถึงอ็อบเจ็กต์เดียวกันกับที่ object_2 อ้างอิงobject_3 . a = 2 ; message (); // แสดงผล 1 2 2 object_2 = object_1 ; // ตอนนี้ object_2 อ้างอิงถึงอ็อบเจ็กต์เดียวกันกับ object_1 // object_3 ยังคงอ้างอิงถึงสิ่งที่ object_2 อ้างอิงอยู่ก่อนหน้านี้message (); // แสดงผล 1 1 2 object_2 . a = 7 ; // แก้ไขค่าของ object_1 message (); // แสดงผล 7 7 2object_3.a = 5 ; // object_3 ไม่เปลี่ยนแปลง object_2 message ( ); // แสดง ผล7 7 5object_3 = object_2 ; object_3.a = 4 ; // object_3 เปลี่ยนค่า object_1 และ object_2 message ( ); // แสดง 4 4 4/** * พิมพ์ข้อความ console.log */ function message () { console . log ( object_1 . a + " " + object_2 . a + " " + object_3 . a ); }

การมอบหมายงานแบบแยกส่วน

ใน JavaScript ของ Mozilla ตั้งแต่เวอร์ชัน 1.7 เป็นต้นมา การกำหนดค่าแบบแยกส่วน (destructuring assignment) อนุญาตให้กำหนดค่าส่วนต่างๆ ของโครงสร้างข้อมูลให้กับตัวแปรหลายตัวพร้อมกันได้ ด้านซ้ายของการกำหนดค่าคือรูปแบบที่คล้ายกับออบเจ็กต์/อาร์เรย์แบบซ้อนกันโดยพลการ ซึ่งมีค่า l-l ค่าอยู่ที่ส่วนปลายสุดที่จะรับโครงสร้างย่อยของค่าที่ถูกกำหนด

let a , b , c , d , e ; [ a , b , c ] = [ 3 , 4 , 5 ]; console . log ( ` ${ a } , ${ b } , ${ c } ` ); // แสดงผล: 3,4,5 e = { foo : 5 , bar : 6 , baz : [ 'Baz' , 'Content' ]}; const arr = []; ({ baz : [ arr [ 0 ], arr [ 3 ]], foo : a , bar : b } = e ); console . log ( ` ${ a } , ${ b } , ${ arr } ` ); // แสดงผล: 5,6,Baz,,,Content [ a , b ] = [ b , a ]; // สลับเนื้อหาของ a และ b console . log ( a + ',' + b ); // แสดงผล: 6,5[ a , b , c ] = [ 3 , 4 , 5 ]; // การเรียงสับเปลี่ยน[ a , b , c ] = [ b , c , a ]; console . log ( ` ${ a } , ${ b } , ${ c } ` ); // แสดงผล: 4,5,3

ตัวดำเนินการกระจาย/พัก

มาตรฐาน ECMAScript 2015 ได้แนะนำ...ตัวดำเนินการอาร์เรย์ " " สำหรับแนวคิดที่เกี่ยวข้องของ "ไวยากรณ์การกระจาย" [ 16 ]และ "พารามิเตอร์ส่วนที่เหลือ" [ 17 ]การกระจายวัตถุถูกเพิ่มใน ECMAScript 2018

ไวยากรณ์แบบ Spreadเป็นอีกวิธีหนึ่งในการแยกโครงสร้างอาร์เรย์และอ็อบเจ็กต์ สำหรับอาร์เรย์ จะระบุว่าองค์ประกอบต่างๆ ควรใช้เป็นพารามิเตอร์ในการเรียกใช้ฟังก์ชัน หรือเป็นรายการในอาร์เรย์ลิเทอรัล สำหรับอ็อบเจ็กต์ สามารถใช้เพื่อรวมอ็อบเจ็กต์เข้าด้วยกัน หรือเขียนทับคุณสมบัติได้

กล่าวอีกนัยหนึ่ง " ..." แปลง " [...foo]" เป็น " [foo[0], foo[1], foo[2]]" และ " this.bar(...foo);" เป็น " this.bar(foo[0], foo[1], foo[2]);" และ " { ...bar }" เป็น{ prop: bar.prop, prop2: bar.prop2 }"

const a = [ 1 , 2 , 3 , 4 ];// สามารถใช้ได้หลายครั้งในนิพจน์เดียวกันconst b = [... a , ... a ]; // b = [1, 2, 3, 4, 1, 2, 3, 4];// สามารถใช้ร่วมกับสิ่งของที่ไม่ต้องกระจายตัวได้const c = [ 5 , 6 , ... a , 7 , 9 ]; // c = [5, 6, 1, 2, 3, 4, 7, 9];// เพื่อเปรียบเทียบ การทำเช่นนี้โดยไม่ใช้ตัวดำเนินการกระจาย (spread operator)// สร้างอาร์เรย์ซ้อนกันconst d = [ a , a ]; // d = [[1, 2, 3, 4], [1, 2, 3, 4]]// การทำงานแบบเดียวกันกับการเรียกใช้ฟังก์ชันฟังก์ชันfoo ( arg1 , arg2 , arg3 ) {console.log ( ` $ { arg1 } : ${ arg2 } : ${ arg3 } ` ) ;}// ผู้ใช้สามารถใช้งานได้แม้ว่าจะส่งพารามิเตอร์มากกว่าที่ฟังก์ชันจะใช้ก็ตามฟู(... ); // "1:2:3" → foo(a[0], a[1], a[2], a[3]);// ผู้ใช้สามารถผสมผสานกับพารามิเตอร์ที่ไม่กระจายได้ฟู( 5 , ... , 6 ); // "5:1:2" → foo(5, a[0], a[1], a[2], a[3], 6);// เพื่อเปรียบเทียบ การทำเช่นนี้โดยไม่ใช้ตัวดำเนินการกระจาย (spread operator)// กำหนดค่าอาร์เรย์ให้กับ arg1 และไม่กำหนดค่าใดๆ ให้กับพารามิเตอร์อื่นๆfoo ( a ); // "1,2,3,4:undefined:undefined"const bar = { a : 1 , b : 2 , c : 3 };// คำสั่งนี้จะคัดลอกวัตถุconst copy = { ... bar }; // copy = { a: 1, b: 2, c: 3 };// ค่า "b" จะถูกแทนที่ในที่นี้const override = { ... bar , b : 4 }; // override = { a: 1, c: 3, b: 4 }

เมื่อ...ใช้ในประกาศ ฟังก์ชัน จะบ่งชี้ถึงพารามิเตอร์ส่วนที่เหลือพารามิเตอร์ส่วนที่เหลือจะต้องเป็นพารามิเตอร์ที่มีชื่อตัวสุดท้ายในรายการพารามิเตอร์ของฟังก์ชัน โดยจะได้รับค่าArrayเป็นอาร์กิวเมนต์ที่ส่งผ่านไปยังฟังก์ชันเกินกว่าค่าของพารามิเตอร์ที่มีชื่อตัวอื่นๆ กล่าวอีกนัยหนึ่งคือ มันจะได้รับ "ส่วนที่เหลือ" ของอาร์กิวเมนต์ที่ส่งไปยังฟังก์ชัน (จึงเป็นที่มาของชื่อ)

ฟังก์ชันfoo ( a , b , ... c ) { console . log ( c . length ); }foo ( 1 , 2 , 3 , 4 , 5 ); // "3" → c = [3, 4, 5] foo ( 'a' , 'b' ); // "0" → c = []

พารามิเตอร์ REST คล้ายกับargumentsออบเจ็กต์ใน JavaScript ซึ่งเป็นออบเจ็กต์ที่มีลักษณะคล้ายอาร์เรย์ที่ประกอบด้วยพารามิเตอร์ทั้งหมด (ทั้งที่มีชื่อและไม่มีชื่อ) ในการเรียกใช้ฟังก์ชันปัจจุบัน อย่างไรก็ตามargumentsพารามิเตอร์ REST เป็นออบเจ็กต์จริง ดังนั้นจึง สามารถใช้ Arrayเมธอดต่างๆ เช่น `input` .slice()และ `input` กับพารามิเตอร์เหล่านี้ได้โดยตรง.sort()

การเปรียบเทียบ

==เท่ากัน
!=ไม่เท่ากัน
>มากกว่า
>=มากกว่าหรือเท่ากับ
<น้อยกว่า
<=น้อยกว่าหรือเท่ากับ
===เหมือนกัน (เท่ากันและเป็นประเภทเดียวกัน)
!==ไม่เหมือนกัน

ตัวแปรที่อ้างอิงถึงวัตถุจะเท่ากันหรือเหมือนกันก็ต่อเมื่ออ้างอิงถึงวัตถุเดียวกันเท่านั้น:

const obj1 = { a : 1 }; const obj2 = { a : 1 }; const obj3 = obj1 ; console . log ( obj1 == obj2 ); //false console . log ( obj3 == obj1 ); //true console . log ( obj3 === obj1 ); //true

ดูเพิ่มเติมที่ สตริง

ตรรกะ

JavaScript มีตัวดำเนินการตรรกะสี่แบบ:

ในบริบทของการดำเนินการทางตรรกะ นิพจน์ใดๆ จะมีค่าเป็นจริง ยกเว้นนิพจน์ต่อไปนี้:

  • สตริง: "", '',
  • ตัวเลข: 0, -0, NaN,
  • พิเศษ: null, undefined,
  • ค่าบูลีน: false.

ฟังก์ชันบูลีนสามารถใช้เพื่อแปลงเป็นชนิดข้อมูลพื้นฐานได้อย่างชัดเจนBoolean:

// เฉพาะสตริงว่าง เท่านั้นที่จะคืนค่า false console.log( Boolean ( " " ) === false ) ; console.log ( Boolean ( " false " ) === true ); console.log ( Boolean ( " 0" ) === true ) ;// เฉพาะค่าศูนย์และ NaN เท่านั้นที่จะคืนค่าเป็น false console.log ( Boolean ( NaN ) === false ) ; console.log ( Boolean ( 0 ) === false ) ; console.log ( Boolean ( -0 ) === false ) ; // เทียบเท่ากับ-1 * 0 console.log ( Boolean ( -2 ) === true ) ;// อ็อบเจ็กต์ ทั้งหมด คืน ค่าtrue console.log ( Boolean ( this ) === true ); console.log ( Boolean ({}) === true ) ; console.log ( Boolean ( [ ]) === true ) ;// ประเภทเหล่านี้ คืนค่าfalse console.log ( Boolean ( null ) === false ); console.log ( Boolean ( undefined ) === false ); // เทียบเท่ากับ Boolean()

ตัวดำเนินการ NOT จะประเมินตัวถูกดำเนินการเป็นค่าบูลีนและส่งคืนค่าปฏิเสธ การใช้ตัวดำเนินการนี้สองครั้งติดต่อกัน ใน รูปแบบ ปฏิเสธสอง ครั้ง จะแปลงนิพจน์ให้เป็นค่าบูลีนโดยตรง

console.log ( ! 0 === Boolean ( ! 0 ) ); console.log ( Boolean ( ! 0 ) === !! 1 ) ; console.log ( !! 1 === Boolean ( 1 ) ) ; console.log ( !! 0 === Boolean ( 0 ) ); console.log ( Boolean ( 0 ) === ! 1 ) ; console.log ( ! 1 === Boolean ( ! 1 )); console.log ( ! " " === Boolean ( ! " " ) ); console.log ( Boolean ( ! " " ) === !! "s" ) ; console.log ( !! " s" === Boolean ( "s" ) ) ; console.log ( !! " " === Boolean ( "" ) ) ; console.log ( Boolean ( " " " ) === ! " s " ) ; console . log ( ! "s" === Boolean ( ! "s" ));

ตัวดำเนินการแบบไตรภาค (ternary operator) สามารถใช้สำหรับการแปลงแบบชัดเจนได้เช่นกัน:

console.log ([] == false ) ; console.log ([] ? true : false ) ; // truthy”, แต่การเปรียบเทียบใช้ [].toString() console.log ([ 0 ] == false ); console.log ([ 0 ] ? true : false ) ; // [0].toString() == "0" console.log ( " 0 " == false ) ; console.log ( " 0 " ? true : false ) ; // " 0 " → 0 ... ( 0 == 0) ... 0 ← false console.log ([ 1 ] == true ); console.log ([ 1 ] ? true : false ) ; // [1].toString() == "1" console.log ( " 1" == true ) ; console.log ( " 1" ? true : false ); // "1" → 1 ... ( 1 == 1) ... 1 ← true console . console.log ([ 2 ] != true ); console.log ([ 2 ] ? true : false ) ; // [2].toString() == "2" console.log ( " 2 " != true ); console.log ( " 2" ? true : false ) ; // "2" → 2 ... (2 != 1) ... 1 ← true

นิพจน์ที่ใช้คุณสมบัติเช่นการเพิ่มค่าหลัง (post–incrementation i++) จะมีผลข้างเคียง ที่คาดการณ์ได้ JavaScript มีการประเมินนิพจน์แบบลัดวงจร ตัวถูกดำเนินการทางขวาจะถูกดำเนินการก็ต่อเมื่อตัวถูกดำเนินการทางซ้ายไม่เพียงพอที่จะกำหนดค่าของนิพจน์เท่านั้น

console.log ( a || b ); // เมื่อ a เป็นจริง ก็ไม่มีเหตุผลที่จะประเมิน b console.log ( a && b ); // เมื่อ a เป็นเท็จ ก็ไม่มีเหตุผลที่จะประเมิน b console.log ( c ? t : f ); // เมื่อ c เป็น จริง ก็ไม่มีเหตุผลที่จะประเมินf

ใน JavaScript และJScript เวอร์ชันแรกๆ ตัวดำเนินการตรรกะแบบไบนารีจะส่งคืนค่าบูลีน (เช่นเดียวกับภาษาโปรแกรมที่พัฒนามาจากภาษา C ส่วนใหญ่) อย่างไรก็ตาม การใช้งานในปัจจุบันทั้งหมดจะส่งคืนค่าตัวถูกดำเนินการตัวใดตัวหนึ่งแทน

console.log ( a || b ); // ถ้าa เป็นจริง ให้คืนค่า a มิฉะนั้นให้คืนค่า b console.log (a && b ) ; // ถ้าa เป็นเท็จ ให้คืนค่า a มิฉะนั้นให้คืนค่าb

โปรแกรมเมอร์ที่คุ้นเคยกับพฤติกรรมในภาษา C อาจรู้สึกแปลกใจกับคุณสมบัตินี้ แต่คุณสมบัตินี้ช่วยให้สามารถแสดงรูปแบบต่างๆ เช่นการรวมค่าว่าง (null coalescing ) ได้อย่างกระชับยิ่งขึ้น

const s = t || "(default)" ; // กำหนดค่า t หรือค่าเริ่มต้น หาก t เป็นค่าว่าง หรือไม่มีค่าเริ่มต้น เป็นต้น

การกำหนดเชิงตรรกะ

??=การกำหนดค่าว่าง
||=การกำหนดค่าแบบตรรกะหรือ
&&=ตรรกะและการมอบหมาย

บิตไวส์

JavaScript รองรับตัวดำเนินการบิตแบบไบนารี ต่อไปนี้ :

&และ
|หรือ
^เอ็กซ์ออร์
!ไม่
<<เลื่อนไปทางซ้าย (เติมศูนย์ที่ด้านขวา)
>>เลื่อนไปทางขวา (การส่งต่อเครื่องหมาย); สำเนาของบิตซ้ายสุด (บิตเครื่องหมาย) จะถูกเลื่อนเข้ามาจากทางซ้าย
>>>เลื่อนไปทางขวา (เติมศูนย์ที่ด้านซ้าย) สำหรับตัวเลขบวก>>จะ>>>ได้ผลลัพธ์เดียวกัน

ตัวอย่าง:

const x = 11 & 6 ; console.log ( x ) ; // 2

JavaScript รองรับตัวดำเนินการบิตแบบเอกภาค ต่อไปนี้ :

~ไม่ใช่ (กลับบิต)

การกำหนดค่าแบบบิตไวส์

JavaScript รองรับตัวดำเนินการกำหนดค่าแบบไบนารีต่อไปนี้:

&=และ
|=หรือ
^=xor
<<=เลื่อนไปทางซ้าย (เติมศูนย์ที่ด้านขวา)
>>=เลื่อนไปทางขวา (การส่งต่อเครื่องหมาย); สำเนาของบิตซ้ายสุด (บิตเครื่องหมาย) จะถูกเลื่อนเข้ามาจากทางซ้าย
>>>=เลื่อนไปทางขวา (เติมศูนย์ที่ด้านซ้าย) สำหรับตัวเลขบวก>>=จะ>>>=ได้ผลลัพธ์เดียวกัน

ตัวอย่าง:

let x = 7 ; console.log ( x ); // 7 x << = 3 ; console.log ( x ) ; // 7->14- > 28-> 56

สตริง

=งานที่มอบหมาย
+การต่อกัน
+=เชื่อมต่อและกำหนดค่า

ตัวอย่าง:

ให้str = "ab" + "cd" ; // "abcd" str += "e" ; // "เอบีซี"const str2 = "2" + 2 ; // "22" ไม่ใช่ "4" หรือ 4

??

ตัวดำเนินการที่ใกล้ที่สุดของJavaScript?? คือ "ตัวดำเนินการรวมค่า nullish" ซึ่งถูกเพิ่มเข้าไปในมาตรฐานในECMAScriptฉบับที่ 11 [ 18 ]ในเวอร์ชันก่อนหน้า สามารถใช้งานได้ผ่าน ปลั๊กอิน BabelและในTypeScriptโดยจะประเมินตัวถูกดำเนินการทางซ้าย และหากค่าผลลัพธ์ไม่ใช่ "nullish" ( nullหรือundefined) จะใช้ค่านั้นเป็นผลลัพธ์ มิฉะนั้น จะประเมินตัวถูกดำเนินการทางขวาและใช้ค่าที่ได้เป็นผลลัพธ์

ในตัวอย่างต่อไปนี้aค่าของ จะถูกกำหนดให้เป็นbถ้าค่าของbไม่ใช่nullหรือundefinedมิฉะนั้นจะถูกกำหนดให้เป็น 3

const a = b ?? 3 ;

ก่อนที่จะมีตัวดำเนินการรวมค่าแบบ nullish โปรแกรมเมอร์จะใช้ตัวดำเนินการตรรกะ OR ( ||) แต่ในขณะที่ ตัวดำเนินการ OR ค้นหาค่าที่เป็นเท็จ ??โดยเฉพาะตัว ดำเนินการ OR จะค้นหาค่าที่เป็นเท็จ ใดๆ ก็ได้ เช่น , , , , , และแน่นอนnullundefined||nullundefined""0NaNfalse

ในตัวอย่างต่อไปนี้aจะถูกกำหนดค่าเป็นbถ้าค่าของ เป็นค่า ที่ bเป็นจริงมิฉะนั้นจะถูกกำหนดค่าเป็น 3

const a = b || 3 ;

โครงสร้างควบคุม

ประโยคผสม

วงเล็บปีกกาคู่หนึ่ง{ }และลำดับของคำสั่งที่อยู่ภายในวงเล็บนั้นประกอบกันเป็นคำสั่งเชิงประกอบ ซึ่งสามารถใช้ได้ทุกที่ที่สามารถใช้คำสั่งทั่วไปได้

ถ้า ... มิฉะนั้น

ถ้า( expr ) { //คำสั่งต่างๆ} มิฉะนั้นถ้า( expr2 ) { //คำสั่งต่างๆ} มิฉะนั้น{ //คำสั่งต่างๆ}

ตัวดำเนินการแบบมีเงื่อนไข (แบบสามทาง)

ตัวดำเนินการเงื่อนไขสร้างนิพจน์ที่ประเมินค่าได้เป็นหนึ่งในสองนิพจน์ ขึ้นอยู่กับเงื่อนไข ซึ่งคล้ายกับ คำสั่ง ifที่เลือกคำสั่งหนึ่งในสองคำสั่งเพื่อดำเนินการ ขึ้นอยู่กับเงื่อนไข กล่าวคือ ตัวดำเนินการเงื่อนไขใช้กับนิพจน์ ในขณะที่ifใช้กับคำสั่ง

const result = condition ? expression : alternative ;

เหมือนกับ:

ถ้า( เงื่อนไข) { const result = expression ; } else { const result = alternative ; }

แตกต่างจาก คำสั่ง ifตรงที่ตัวดำเนินการเงื่อนไขไม่สามารถละเว้น "ส่วน else" ได้

คำสั่งสวิตช์

ไวยากรณ์ของคำสั่ง switch ใน JavaScript มีดังนี้:

switch ( expr ) { case SOMEVALUE : // คำสั่ง; break ; case ANOTHERVALUE : // คำสั่งสำหรับเมื่อ ANOTHERVALUE || ORANOTHERONE // ไม่มีคำสั่ง break ข้ามไปยัง case ถัดไปcase ORANOTHERONE : // คำสั่งเฉพาะสำหรับ ORANOTHERONE (เช่น !ANOTHERVALUE && ORANOTHER); break ; // สิ้นสุดที่นี่case YETANOTHER : // คำสั่ง; break ; default : // คำสั่ง; break ; }
  • break;เป็นตัวเลือกเสริม แต่โดยปกติแล้วมักจำเป็น เพราะมิเช่นนั้นการทำงานของโค้ดจะดำเนินต่อไปยังส่วนของบล็อกกรณีถัดไป พฤติกรรมการทำงาน ต่อเนื่อง นี้ สามารถใช้ได้เมื่อชุดคำสั่งเดียวกันใช้ได้ในหลายกรณี ซึ่งเป็นการสร้างความสัมพันธ์แบบ "หรือ " ระหว่างกรณีเหล่านั้น
  • เพิ่มคำสั่ง break ไว้ท้ายกรณีสุดท้ายเพื่อเป็นการป้องกันไว้ก่อน ในกรณีที่มีการเพิ่มกรณีเพิ่มเติมในภายหลัง
  • สามารถใช้ค่าตัวอักษรสตริงสำหรับค่าตัวพิมพ์ใหญ่-เล็กได้เช่นกัน
  • สามารถใช้นิพจน์แทนค่าได้
  • กรณีเริ่มต้น (ไม่บังคับ) จะถูกดำเนินการเมื่อนิพจน์ไม่ตรงกับกรณีอื่นใดที่ระบุไว้
  • จำเป็นต้องใส่เหล็กดัดฟัน

สำหรับลูป

ไวยากรณ์ของลูป for ใน JavaScript มีดังนี้:

สำหรับ( ค่าเริ่มต้น; เงื่อนไข; คำสั่งลูป) { /*  คำสั่งจะถูกดำเนินการทุกครั้ง ที่ลูป for{} ทำงาน ตราบใดที่ เงื่อนไขเป็นจริง */ }

หรือ

สำหรับ( เริ่มต้น; เงื่อนไข; คำสั่งวนซ้ำ( การวนซ้ำ)) // คำสั่งเดียว

สำหรับ ... ในลูป

ไวยากรณ์ของ JavaScript for ... in loopมีดังนี้:

for ( var property_name in some_object ) { // คำสั่ง using some_object[property_name]; }
  • วนลูปผ่านคุณสมบัติที่สามารถแจงนับได้ทั้งหมดของวัตถุ
  • ลูปนี้จะวนซ้ำผ่านดัชนีที่ใช้ทั้งหมดของอาร์เรย์ รวมถึงคุณสมบัติที่ผู้ใช้กำหนดเองของออบเจ็กต์อาร์เรย์ (ถ้ามี) ดังนั้น การใช้ลูป for แบบดั้งเดิมที่มีดัชนีตัวเลขอาจจะดีกว่าเมื่อวนซ้ำผ่านอาร์เรย์
  • มีความแตกต่างกันระหว่างเว็บเบราว์เซอร์ต่างๆ เกี่ยวกับคุณสมบัติที่จะแสดงผลเมื่อใช้คำสั่งลูป for...in ในทางทฤษฎี สิ่งนี้ถูกควบคุมโดยคุณสมบัติสถานะภายในที่กำหนดโดยมาตรฐาน ECMAscript ที่เรียกว่า "DontEnum" แต่ในทางปฏิบัติ เบราว์เซอร์แต่ละตัวจะส่งคืนชุดคุณสมบัติที่แตกต่างกันเล็กน้อยในระหว่างการตรวจสอบภายใน จึงเป็นประโยชน์ที่จะทดสอบคุณสมบัติที่กำหนดโดยใช้ดังนั้น การเพิ่มเมธอดลงในต้นแบบอาร์เรย์ด้วยอาจทำให้ลูปวนซ้ำตามชื่อของเมธอดนั้นif(some_object.hasOwnProperty(property_name)){...}Array.prototype.newMethod=function(){...}for ... in

ลูป while

ไวยากรณ์ของลูป while ใน JavaScript มีดังนี้:

ในขณะที่( เงื่อนไข) { คำสั่งที่ 1 ; คำสั่งที่ 2 ; คำสั่งที่ 3 ; ... }

ทำ ... ลูป while

ไวยากรณ์ของ JavaScript do ... while loopมีดังนี้:

ทำ{ คำสั่งที่ 1 ; คำสั่งที่ 2 ; คำสั่งที่ 3 ; ... } ในขณะที่( เงื่อนไข);

กับ

คำสั่ง `with` จะเพิ่มคุณสมบัติและเมธอดทั้งหมดของอ็อบเจ็กต์ที่กำหนดเข้าไปในขอบเขตของบล็อกถัดไป ทำให้สามารถอ้างอิงถึงคุณสมบัติและเมธอดเหล่านั้นได้ราวกับว่าเป็นตัวแปรโลคอล

ด้วย( เอกสาร) { const a = getElementById ( 'a' ); const b = getElementById ( 'b' ); const c = getElementById ( 'c' ); };
  • โปรดสังเกตว่าไม่มีคำว่าdocument. นำหน้า การเรียกใช้getElementById()แต่ละครั้ง

ความหมายคล้ายคลึงกับคำสั่ง with ในภาษาปาสคา

เนื่องจากการใช้คำสั่ง `with` ขัดขวางประสิทธิภาพของโปรแกรมและเชื่อกันว่าจะลดความชัดเจนของโค้ด (เพราะตัวแปรใดๆ ก็ตามอาจเป็นคุณสมบัติจากคำสั่ง ` with` ที่อยู่ภายใน ) ดังนั้นจึงไม่อนุญาตให้ใช้คำสั่งนี้ในโหมดเข้มงวด (strict mode )

ป้ายกำกับ

JavaScript รองรับป้ายกำกับแบบซ้อนกันในการใช้งานส่วนใหญ่ ลูปหรือบล็อกสามารถติดป้ายกำกับสำหรับคำสั่ง break และลูปสำหรับcontinue. แม้ว่าgotoจะเป็นคำสงวน[ 19 ]gotoก็ไม่ได้ถูกนำไปใช้ใน JavaScript

loop1 : for ( let a = 0 ; a < 10 ; ++ a ) { if ( a === 4 ) break loop1 ; // หยุดหลังจากความพยายามครั้งที่ 4 console . log ( 'a = ' + a ); loop2 : for ( let b = 0 ; b < 10 ; ++ b ) { if ( b === 3 ) continue loop2 ; // ข้ามหมายเลข 3 if ( b === 6 ) continue loop1 ; // ดำเนินการต่อในลูปแรก ไม่แสดง 'finished' console . log ( 'b = ' + b ); } // สิ้นสุด loop2 console . log ( 'finished' ); } // สิ้นสุด loop1 block1 : { console . log ( 'Hello' ); // แสดง 'Hello' break block1 ; console . log ( 'World' ); // จะไม่มาถึงตรงนี้} goto block1 ; // เกิดข้อผิดพลาดในการแยก วิเคราะห์

ฟังก์ชัน

ฟังก์ชันคือบล็อกที่มีรายการพารามิเตอร์ (อาจว่างเปล่าก็ได้) ซึ่งโดยปกติจะมีชื่อกำกับไว้ ฟังก์ชันอาจใช้ตัวแปรโลคอลได้ หากผู้ใช้ปิดฟังก์ชันโดยไม่มีคำสั่ง return ค่าที่ได้จะเป็น undefined

ฟังก์ชันgcd ( number1 , number2 ) { ถ้า( isNaN ( number1 * number2 )) ให้โยนTypeError ( "ไม่อนุญาตให้ใช้อาร์กิวเมนต์ที่ไม่ใช่ตัวเลข" ); number1 = Math . round ( number1 ); number2 = Math . round ( number2 ); ให้difference = number1 - number2 ; ถ้าdifference === 0 ) ให้คืนค่า number1 ; ให้คืนค่า difference > 0 ? gcd ( number2 , difference ) : gcd ( number1 , - difference ); } console . log ( gcd ( 60 , 40 )); // 20//ในกรณีที่ไม่มีวงเล็บตามหลังตัวระบุ 'gcd' ทางด้านขวาของการกำหนดค่าด้านล่าง//'gcd' จะส่งคืนการอ้างอิงไปยังฟังก์ชันนั้นเองโดยไม่ต้องเรียกใช้let mygcd = gcd ; // mygcd และ gcd อ้างอิงถึงฟังก์ชันเดียวกันconsole . log ( mygcd ( 60 , 40 )); // 20

ฟังก์ชันเป็นอ็อบเจ็กต์ระดับเฟิร์สคลาสและสามารถกำหนดให้กับตัวแปรอื่นได้

จำนวนอาร์กิวเมนต์ที่ส่งเมื่อเรียกใช้ฟังก์ชันอาจไม่ตรงกับจำนวนอาร์กิวเมนต์ในนิยามของฟังก์ชันเสมอไป อาร์กิวเมนต์ที่มีชื่อในนิยามที่ไม่มีอาร์กิวเมนต์ที่ตรงกันในการเรียกใช้จะมีค่าเป็น undefined (ซึ่งสามารถแปลงเป็น false ได้โดยปริยาย) ภายในฟังก์ชัน ยังสามารถเข้าถึงอาร์กิวเมนต์ได้ผ่านทาง อ็อบเจ็กต์ argumentsซึ่งจะช่วยให้เข้าถึงอาร์กิวเมนต์ทั้งหมดโดยใช้ดัชนี (เช่น `arguments` ) รวมถึงอาร์กิวเมนต์ที่เกินจำนวนอาร์กิวเมนต์ที่มีชื่อด้วย (ถึงแม้ว่าลิสต์ของอาร์กิวเมนต์จะมีคุณสมบัติ `slice()` แต่ก็ไม่ใช่ตัวอย่างของArrayและไม่มีเมธอดเช่น`.slice()` , `.sort() ` เป็นต้น) arguments[0],arguments[1],...arguments[n].length

ฟังก์ชันadd7 ( x , y ) { ถ้า( ! y ) { y = 7 ; } console . log ( x + y + arguments . length ); }; add7 ( 3 ); // 11 add7 ( 3 , 4 ); // 9

ค่าพื้นฐาน (ตัวเลข บูลีน สตริง) จะถูกส่งผ่านโดยค่า ส่วนอ็อบเจ็กต์จะส่งผ่านโดยการอ้างอิงถึงอ็อบเจ็กต์นั้น

const obj1 = { a : 1 }; const obj2 = { b : 2 }; function foo ( p ) { p = obj2 ; // ไม่สนใจพารามิเตอร์จริงp . b = arguments [ 1 ]; } foo ( obj1 , 3 ); // ไม่มีผลต่อ obj1 เลย 3 เป็นพารามิเตอร์เพิ่มเติมconsole . log ( ` ${ obj1 . a } ${ obj2 . b } ` ); // เขียน 1 3

ฟังก์ชันสามารถประกาศภายในฟังก์ชันอื่นได้ และสามารถเข้าถึงตัวแปรโลคอลของฟังก์ชันภายนอกได้ นอกจากนี้ ฟังก์ชันยังสามารถใช้งาน closure ได้อย่างสมบูรณ์ โดยจดจำตัวแปรโลคอลของฟังก์ชันภายนอกไว้แม้หลังจากฟังก์ชันภายนอกสิ้นสุดการทำงานแล้ว

let t = "Top" ; let bar , baz ; function foo () { let f = "foo var" ; bar = function () { console . log ( f ) }; baz = function ( x ) { f = x ; }; } foo (); baz ( "baz arg" ); bar (); // "baz arg" (ไม่ใช่ "foo var") แม้ว่า foo() จะออกจากโปรแกรมแล้วconsole . log ( t ); // Top

ฟังก์ชันนิรนามเป็นเพียงฟังก์ชันที่ไม่มีชื่อ และสามารถเขียนได้โดยใช้สัญลักษณ์ฟังก์ชันหรือสัญลักษณ์ลูกศร ในตัวอย่างที่เทียบเท่ากันเหล่านี้ฟังก์ชันนิรนามจะถูกส่งไปยัง ฟังก์ชัน mapและนำไปใช้กับแต่ละองค์ประกอบของอาร์เรย์[ 20 ]

[ 1 , 2 , 3 ]. map ( function ( x ) { return x * 2 ;); //คืนค่า [2,4,6] [ 1 , 2 , 3 ]. map (( x ) => { return x * 2 ;}); //ผลลัพธ์เหมือนกัน

ฟังก์ชันตัวสร้างจะแสดงโดยการวางเครื่องหมาย * หลังคำหลักฟังก์ชัน และประกอบด้วยคำสั่ง yieldอย่างน้อยหนึ่งคำสั่ง ผลลัพธ์คือการส่งค่ากลับและหยุดการทำงานที่สถานะปัจจุบัน การประกาศฟังก์ชันตัวสร้างจะส่งคืนค่าตัววนซ้ำ การเรียกใช้iterator.next() ครั้งถัดไป จะดำเนินการต่อจนกว่าจะถึงyield ครั้งถัดไป เมื่อตัววนซ้ำส่งคืนค่าโดยไม่ใช้คำสั่ง yield จะไม่มีค่าเหลืออยู่ และ คุณสมบัติ doneของตัววนซ้ำจะถูกตั้งค่าเป็นtrue [ 21 ]

ยกเว้น อุปกรณ์ iOSจาก Apple แล้ว ตัวสร้างจะไม่ถูกนำมาใช้สำหรับเบราว์เซอร์บนอุปกรณ์เคลื่อนที่[ 22 ]

ฟังก์ชัน* generator () { yield "red" ; yield "green" ; yield "blue" ; }let iterator = generator (); let current ;ในขณะที่( current = iterator.next (). value ) console.log ( current ) ; // แสดง สี แดงสีเขียว แล้วก็สีน้ำเงินconsole.log ( iterator.next ( ) . done ) ; // แสดงค่า true

อะซิงโครนัส/อะไวต์

ตัวดำเนินการ await ใน JavaScript (และ TypeScript) สามารถใช้ได้เฉพาะภายในฟังก์ชัน async หรือที่ระดับบนสุดของโมดูลเท่านั้น หากพารามิเตอร์เป็นpromiseการทำงานของฟังก์ชัน async จะดำเนินต่อเมื่อ promise ได้รับการแก้ไขแล้ว (เว้นแต่ promise จะถูกปฏิเสธ ซึ่งในกรณีนี้จะเกิดข้อผิดพลาดที่สามารถจัดการได้ด้วยการจัดการข้อยกเว้น ของ JavaScript ตามปกติ ) หากพารามิเตอร์ไม่ใช่ promise พารามิเตอร์นั้นจะถูกส่งคืนทันที[ 23 ]

ไลบรารีหลายแห่งมีออบเจ็กต์ Promise ที่สามารถใช้กับ await ได้เช่นกัน ตราบใดที่ตรงตามข้อกำหนดสำหรับ Promise ดั้งเดิมของ JavaScript อย่างไรก็ตาม Promise จาก ไลบรารี jQueryไม่เข้ากันกับ Promises/A+ จนกระทั่ง jQuery 3.0 [ 24 ]

ด้านล่างนี้คือตัวอย่าง (ดัดแปลงจาก บทความ [ 25 ] นี้ ):

อินเทอร์เฟซDBResponse { id : string ; rev? : string ; ok? : boolean ; }อินเทอร์เฟซDocument { _id : string ; _rev? : string ; [ key : string ] : any ; }interface Database { post ( doc : object ) : Promise < DBResponse > ; get ( id : string ) : Promise < Document > ; }ประกาศconst db : Database ;ฟังก์ชันอะซิงโครนัcreateNewDoc ( ) : Promise <Document> { const response : DBResponse = await db.post ( { } ) ; const doc : Document = await db.get ( response.id ) ; return doc ; }async function main () : Promise < void > { try { const doc : Document = await createNewDoc (); console . log ( doc ); } catch ( err : Error ) { console . error ( "เกิดข้อผิดพลาดในการสร้างหรือดึงเอกสาร:" , err ); } }หลัก();

Node.jsเวอร์ชัน 8 มีเครื่องมือที่ช่วยให้สามารถใช้เมธอดแบบเรียกกลับมาตรฐานของไลบรารีเป็น Promise ได้[ 26 ]

วัตถุ

เพื่อความสะดวก โดยทั่วไปแล้วประเภทต่างๆ จะถูกแบ่งย่อยออกเป็นประเภทพื้นฐาน (primitives ) และประเภทวัตถุ (objects ) วัตถุคือสิ่งที่มีเอกลักษณ์ (มีค่าเท่ากับตัวมันเองเท่านั้น) และทำหน้าที่แมปชื่อคุณสมบัติกับค่า ("ช่อง" ใน ศัพท์เฉพาะ ของการเขียนโปรแกรมแบบใช้ต้นแบบ ) วัตถุอาจถูกมองว่าเป็นอาร์เรย์แบบเชื่อมโยงหรือแฮช และมักถูกนำไปใช้โดยใช้โครงสร้างข้อมูลเหล่านี้ อย่างไรก็ตาม วัตถุมีคุณสมบัติเพิ่มเติม เช่นสายโซ่ต้นแบบ (prototype chain ) ซึ่งอาร์เรย์แบบเชื่อมโยงทั่วไปไม่มี

JavaScript มีอ็อบเจ็กต์พื้นฐานหลายประเภท ได้แก่Array<object>, Boolean<object>, Date<object>, Function<object>, Math<object>, Number<object> ObjectและRegExp<object> Stringอ็อบเจ็กต์อื่นๆ เรียกว่า "อ็อบเจ็กต์โฮสต์" ซึ่งไม่ได้กำหนดโดยภาษา แต่กำหนดโดยสภาพแวดล้อมรันไทม์ ตัวอย่างเช่น ในเบราว์เซอร์ อ็อบเจ็กต์โฮสต์ทั่วไปจะอยู่ใน DOM (หน้าต่าง ฟอร์ม ลิงก์ ฯลฯ)

การสร้างวัตถุ

สามารถสร้างอ็อบเจ็กต์ได้โดยใช้คอนสตรัคเตอร์หรืออ็อบเจ็กต์ลิเทอรัล คอนสตรัคเตอร์สามารถใช้ฟังก์ชันในตัวของอ็อบเจ็กต์หรือฟังก์ชันที่กำหนดเองก็ได้ ตามธรรมเนียมแล้ว ฟังก์ชันคอนสตรัคเตอร์มักมีชื่อที่ขึ้นต้นด้วยตัวอักษรตัวใหญ่:

// คอนสตรัคเตอร์const anObject = new Object ();// อ็อบเจ็กต์ลิเทอรัลconst objectA = {}; const objectA2 = {}; // A != A2, {}s สร้างอ็อบเจ็กต์ใหม่เป็นสำเนาconst objectB = { index1 : 'value 1' , index2 : 'value 2' };// คอนสตรัคเตอร์แบบกำหนดเอง (ดูด้านล่าง)

อ็อบเจ็กต์ลิเทอรัลและอาร์เรย์ลิเทอรัลช่วยให้สามารถสร้างโครงสร้างข้อมูลที่ยืดหยุ่นได้อย่างง่ายดาย:

const myStructure = { name : { first : "Mel" , last : "Smith" }, age : 33 , hobbies : [ "chess" , "jogging" ] };

นี่คือพื้นฐานของJSONซึ่งเป็นสัญลักษณ์ที่เรียบง่ายที่ใช้ไวยากรณ์คล้าย JavaScript สำหรับการแลกเปลี่ยนข้อมูล

วิธีการ

เมธอดก็คือฟังก์ชันที่ถูกกำหนดให้กับชื่อคุณสมบัติของอ็อบเจ็กต์ แตกต่างจากภาษาโปรแกรมเชิงวัตถุหลายภาษา ใน JavaScript ที่เกี่ยวข้องกับวัตถุนั้นไม่มีความแตกต่างระหว่างการนิยามฟังก์ชันและการนิยามเมธอด ความแตกต่างจะเกิดขึ้นในระหว่างการเรียกใช้ฟังก์ชันต่างหาก กล่าวคือ ฟังก์ชันสามารถถูกเรียกใช้ในฐานะเมธอดได้

เมื่อเรียกใช้เป็นเมธอด ตัวแปรโลคอลมาตรฐาน ` this`จะถูกกำหนดค่าโดยอัตโนมัติเป็นอินสแตนซ์ของอ็อบเจ็กต์ทางด้านซ้ายของเครื่องหมาย " . " (นอกจากนี้ยังมี เมธอด `call`และ`apply`ที่สามารถกำหนดค่า`this` ได้ อย่างชัดเจน—บางแพ็กเกจ เช่นjQuery มีวิธีการจัดการ `this`ที่ค่อนข้างแปลก)

ในตัวอย่างด้านล่าง Foo ถูกใช้เป็นคอนสตรัคเตอร์ คอนสตรัคเตอร์นั้นไม่มีอะไรพิเศษ – มันเป็นเพียงฟังก์ชันธรรมดาที่ใช้เริ่มต้นค่าให้กับอ็อบเจ็กต์ เมื่อใช้ร่วมกับ คีย์เวิร์ด newตามปกติมันจะกำหนดค่าเริ่มต้นให้กับอ็อบเจ็กต์ว่างเปล่าที่สร้างขึ้นใหม่

โปรดสังเกตว่าในตัวอย่างด้านล่าง Foo เพียงแค่กำหนดค่าให้กับช่องต่างๆ ซึ่งบางช่องเป็นฟังก์ชัน ดังนั้นจึงสามารถกำหนดฟังก์ชันที่แตกต่างกันให้กับอินสแตนซ์ที่แตกต่างกันได้ ตัวอย่างนี้ไม่มีการสร้างต้นแบบ (prototyping)

ฟังก์ชันpx () { คืนค่าthis . prefix + "X" ; }ฟังก์ชันFoo ( yz ) { this . prefix = "a-" ; ถ้า( yz > 0 ) { this . pyz = function () { return this . prefix + "Y" ; }; } else { this . pyz = function () { return this . prefix + "Z" ; }; } this . m1 = px ; return this ; }const foo1 = new Foo ( 1 ); const foo2 = new Foo ( 0 ); foo2.prefix = " b- " ;console.log ( "foo1/2" + foo1.pyz ( ) + foo2.pyz ( ) ) ; // foo1/ 2 aY bZfoo1.m3 = px ; // กำหนดค่าให้กับฟังก์ชัน เอง ไม่ใช่ผลลัพธ์ที่ประเมิน แล้วเช่น ไม่ใช่ px() const baz = { "prefix" : " c-" }; baz.m4 = px ; // ไม่จำเป็นต้องมีคอนสตรัค เตอร์เพื่อสร้างอ็อบเจ็กต์console.log ( "m1/m3/m4" + foo1.m1 ( ) + foo1.m3() + baz.m4 ( ) ) ; // m1 / m3 / m4 aX aX cXfoo1.m2 (); // จะเกิดข้อยกเว้น เนื่องจาก foo1.m2 ไม่มีอยู่จริง

ผู้สร้าง

ฟังก์ชันตัวสร้าง (Constructor functions)ทำหน้าที่กำหนดค่าให้กับช่อง (slots) ของอ็อบเจ็กต์ที่สร้างขึ้นใหม่ ค่าเหล่านั้นอาจเป็นข้อมูลหรือฟังก์ชันอื่นๆ ก็ได้

ตัวอย่าง: การจัดการกับวัตถุ:

ฟังก์ชันMyObject ( attributeA , attributeB ) { this . attributeA = attributeA ; this . attributeB = attributeB ; }MyObject.staticC = "blue" ; // ในฟังก์ชันMyObject ไม่ใช่ในอ็อบเจ็กต์console.log ( MyObject.staticC ) ; // blueconst object = new MyObject ( 'red' , 1000 );console.log ( object.attributeA ) ; // สีแดงconsole.log ( object.attributeB ) ; // 1000console.log ( object.staticC ); // ไม่ได้กำหนดobject.attributeC = new Date ( ) ; // เพิ่มคุณสมบัติใหม่delete object.attributeB ; // ลบคุณสมบัติของอ็อบเจ็กต์ // โปรดทราบว่า ต่างจากใน C++ คำสั่ง delete ไม่ได้เรียกใช้ "destructor" // แต่จะลบคุณสมบัติของอ็อบเจ็กต์แทนconsole.log ( object.attributeB ) ; // ไม่ได้กำหนด

ตัวสร้างนั้นถูกอ้างอิงอยู่ในช่อง สร้างของต้นแบบอ็อบเจ็กต์ดังนั้น

function Foo () {} // การใช้ 'new' จะกำหนดช่องต้นแบบ (ตัวอย่างเช่น// x = new Foo() จะกำหนดต้นแบบของ x เป็น Foo.prototype // และ Foo.prototype มีช่องตัวสร้างที่ชี้กลับไปยัง Foo) const x = new Foo (); // ข้างต้นเกือบเทียบเท่ากับconst y = {}; y . constructor = Foo ; y . constructor (); // ยกเว้นx . constructor == y . constructor ; // true x instanceof Foo ; // true y instanceof Foo ; // false // ต้นแบบของ y คือ Object.prototype ไม่ใช่// Foo.prototype เนื่องจากมันถูกเริ่มต้นด้วย// {} แทนที่จะเป็น new Foo // แม้ว่า Foo จะถูกกำหนดให้เป็นช่องตัวสร้างของ y // แต่ instanceof จะไม่สนใจ - มีเพียงช่องตัวสร้างของต้นแบบของ y เท่านั้นที่ถูกพิจารณา

ฟังก์ชันเป็นอ็อบเจ็กต์ในตัวเอง ซึ่งสามารถใช้สร้างเอฟเฟกต์ที่คล้ายกับ "คุณสมบัติแบบคงที่" (ตามศัพท์เฉพาะของ C++/Java) ดังแสดงด้านล่าง (อ็อบเจ็กต์ฟังก์ชันยังมีprototypeคุณสมบัติพิเศษอีกด้วย ดังที่กล่าวไว้ในหัวข้อ "การสืบทอด" ด้านล่าง)

การลบอ็อบเจ็กต์นั้นไม่ค่อยได้ใช้ เนื่องจากเอนจินการเขียนสคริปต์จะทำการล้างหน่วยความจำของอ็อบเจ็กต์ที่ไม่ได้รับการอ้างอิงอีกต่อไป

มรดก

JavaScript รองรับลำดับชั้นการสืบทอดผ่านการสร้างต้นแบบในลักษณะของ Self

ในตัวอย่างต่อไปนี้ คลาส Derivedสืบทอดมาจาก คลาส Baseเมื่อสร้างd เป็น Derived แล้วการอ้างอิงถึงอินสแตนซ์พื้นฐานของBase จะถูกคัดลอกไปยังd.base

ตัวแปร `Derive` ไม่มีค่าสำหรับ`aBaseFunction`ดังนั้นจึงต้องดึงค่ามาจาก`aBaseFunction` เมื่อมีการเข้าถึง`aBaseFunction`ซึ่งจะเห็นได้ชัดเจนจากการเปลี่ยนแปลงค่าของ`base.aBaseFunction`และการเปลี่ยนแปลงนี้จะสะท้อนให้เห็นในค่าของ` d.aBaseFunction` ด้วย

บางการใช้งานอนุญาตให้เข้าถึงหรือตั้งค่าต้นแบบได้อย่างชัดเจนโดยใช้ ช่อง __proto__ดังแสดงด้านล่าง

ฟังก์ชันBase () { this.anOverride = ฟังก์ชัน() { console.log ( " Base::anOverride() " ) ; } ;this.aBaseFunction = function () { console.log ( " Base::aBaseFunction() " ) ; } ; }ฟังก์ชันDerived ( ) { this.anOverride = ฟังก์ชัน() { console.log ( " Derived::anOverride()" ) ; } ; }const base = new Base ( ); Derived.prototype = base ; // ต้องอยู่ก่อน new Derived() Derived.prototype.constructor = Derived ; // จำเป็นเพื่อให้ `instanceof` ทำงานได้const d = new Derived (); // คัดลอก Derived.prototype ไปยังช่อง prototype ที่ซ่อนอยู่ของอินสแตนซ์d d instanceof Derived ; // true d instanceof Base ; // truebase.aBaseFunction = function () { console.log ( " Base ::aNEWBaseFunction() " ) ; } ;d.anOverride (); // Derived :: anOverride() d.aBaseFunction ( ) ; // Base :: aNEWBaseFunction ( ) console.log ( d.aBaseFunction == Derived.prototype.aBaseFunction ) ; // trueconsole.log ( d .__ proto__ == base ); // true ในการใช้งานที่ใช้ Mozilla เป็นพื้นฐาน และ false ในการใช้งานอื่นๆอีกมากมาย

ภาพต่อไปนี้แสดงให้เห็นอย่างชัดเจนว่าการอ้างอิงถึงต้นแบบจะถูกคัดลอก อย่างไร เมื่อสร้างอินสแตนซ์ แต่การเปลี่ยนแปลงใดๆ ในต้นแบบอาจส่งผลกระทบต่ออินสแตนซ์ทั้งหมดที่อ้างอิงถึงต้นแบบนั้น

ฟังก์ชันm1 () { คืนค่า"หนึ่ง" ; } ฟังก์ชันm2 () { คืนค่า"สอง" ; } ฟังก์ชันm3 () { คืนค่า"สาม" ; }ฟังก์ชันฐาน() {}Base.prototype.m = m2 ; const bar = new Base ( ); console.log ( " bar.m " + bar.m ( ) ) ; // bar.m Twoฟังก์ชันTop () { this . m = m3 ; } const t = new Top ();const foo = new Base ( ); Base.prototype = t ; // ไม่มี ผล ต่อfoo *การอ้างอิง* ไปยัง t ถูกคัดลอกconsole.log ( "foo.m " + foo.m ( )); // foo.m Twoconst baz = new Base (); console.log( " baz.m " + baz.m ( ) ); // baz.m Threet.m = m1 ; // มีผลต่อ baz และคลาสที่สืบทอดอื่นๆconsole.log ( "baz.m1" + baz.m ( ) ) ; // baz.m1 หนึ่ง

ในทางปฏิบัติ มีการนำรูปแบบต่างๆ ของแนวคิดเหล่านี้มาใช้มากมาย และอาจทั้งทรงพลังและสร้างความสับสนได้

การจัดการข้อยกเว้น

JavaScript มี คำสั่ง try ... catch ... finallyจัดการข้อยกเว้นเพื่อจัดการกับข้อผิดพลาดขณะรันไทม์

try ... catch ... finallyคำสั่งนี้ ใช้ดักจับ ข้อยกเว้นที่เกิดจากข้อผิดพลาดหรือคำสั่ง throw โดยมีไวยากรณ์ดังนี้:

try { // คำสั่งที่อาจเกิดข้อยกเว้น} catch ( errorValue ) { // คำสั่งที่จะทำงานเมื่อเกิดข้อยกเว้น} finally { // คำสั่งที่จะทำงานหลังจากนั้นไม่ว่ากรณีใดๆ ก็ตาม}

ในขั้นต้น คำสั่งภายในบล็อก try จะถูกประมวลผล หากเกิดข้อยกเว้น การควบคุมการทำงานของสคริปต์จะเปลี่ยนไปที่คำสั่งในบล็อก catch ทันที โดยข้อยกเว้นนั้นจะถูกส่งเป็นอาร์กิวเมนต์ error มิฉะนั้น บล็อก catch จะถูกข้ามไป บล็อก catch สามารถthrow(errorValue) ได้ หากไม่ต้องการจัดการกับข้อผิดพลาดเฉพาะนั้น

ไม่ว่าในกรณีใด คำสั่งในบล็อก finally จะถูกดำเนินการเสมอ แม้ว่าหน่วยความจำจะถูกจัดการโดยอัตโนมัติ แต่ก็สามารถใช้ส่วนนี้เพื่อดำเนินการล้างทรัพยากรด้วยตนเองได้ (เช่น การปิดไฟล์หรือการเชื่อมต่อ)

สามารถละเว้นส่วน catch หรือส่วน finally ได้ แต่จำเป็นต้องมีอาร์กิวเมนต์ catch

การใช้งานของ Mozilla อนุญาตให้ใช้คำสั่ง catch ได้หลายรายการ ซึ่งเป็นส่วนขยายของมาตรฐาน ECMAScript โดยใช้ไวยากรณ์ที่คล้ายกับที่ใช้ในJava :

try { statement ; } catch ( e if e == "InvalidNameException" ) { statement ; } catch ( e if e == "InvalidIdException" ) { statement ; } catch ( e if e == "InvalidEmailException" ) { statement ; } catch ( e ) { statement ; } finally { statement ; }

ในเบราว์เซอร์ เหตุการณ์ onerrorมักใช้เพื่อดักจับข้อผิดพลาดมากกว่า

onerror = function ( errorValue , url , lineNr ) {...; return true ;};

ฟังก์ชันและเมธอดดั้งเดิม

ประเมิน (นิพจน์)

ประเมินพารามิเตอร์แรกเป็นนิพจน์ ซึ่งสามารถรวมคำสั่งการกำหนดค่าได้ ตัวแปรภายในฟังก์ชันสามารถอ้างอิงได้ด้วยนิพจน์ อย่างไรก็ตามevalถือเป็นความเสี่ยงด้านความปลอดภัยที่สำคัญ เนื่องจากอนุญาตให้ผู้ไม่ประสงค์ดีสามารถเรียกใช้โค้ดตามอำเภอใจได้ ดังนั้นจึงไม่แนะนำให้ใช้[ 27 ]

> ( ฟังก์ชันfoo () { ... var x = 7 ; ... console . log ( "val " + eval ( "x + 2" )); ... })(); val 9 undefined

คุณสมบัติเฉพาะของ TypeScript

TypeScriptซึ่งเป็นส่วนขยายของ JavaScript ที่พัฒนาโดยMicrosoftได้เพิ่มส่วนขยายไวยากรณ์ต่อไปนี้ให้กับ

ในเชิงไวยากรณ์ TypeScript มีความคล้ายคลึงกับJScript .NET อย่างมาก ซึ่งเป็นอีกหนึ่งการใช้งานมาตรฐานภาษา ECMA-262 ของ Microsoft ที่เพิ่มการรองรับการกำหนดประเภทแบบคงที่และคุณสมบัติของภาษาเชิงวัตถุแบบดั้งเดิม เช่น คลาส การสืบทอด อินเทอร์เฟซ และเนมสเปซ นอกจากนี้ยังได้รับแรงบันดาลใจมาจากJavaและC#อีก ด้วย

คำอธิบายประเภท

TypeScript มีระบบตรวจสอบประเภทข้อมูลแบบคงที่ผ่านการระบุประเภท (type annotations) เพื่อให้สามารถตรวจสอบประเภทข้อมูล ได้ ในระหว่างการคอมไพล์

ฟังก์ชันadd ( ซ้าย: ตัวเลข, ขวา: ตัวเลข) : ตัวเลข{ คืนค่าซ้าย+ ขวา; }

ชนิดข้อมูลพื้นฐานจะถูกระบุด้วยตัวพิมพ์เล็กทั้งหมด เช่นnumber, boolean, bigint, และstringชนิดข้อมูลเหล่านี้แตกต่างจากชนิดข้อมูล แบบ กล่อง ( Number, Boolean, เป็นต้น) ซึ่งไม่สามารถดำเนินการกับค่าโดยตรงได้ (เช่นNumberไม่numberสามารถบวก และ ได้) นอกจากนี้ยังมี ชนิดข้อมูล undefinedและnullสำหรับค่าที่เกี่ยวข้องด้วย

ชนิดข้อมูลที่ไม่ใช่ชนิดพื้นฐานอื่นๆ ทั้งหมดจะถูกระบุโดยใช้ชื่อคลาส เช่นErrorอาร์เรย์สามารถเขียนได้สองวิธีที่แตกต่างกัน แต่มีไวยากรณ์เหมือนกันทั้งสองวิธี ได้แก่ ไวยากรณ์แบบเจเนริกArray<T>และรูปแบบย่อT[]ด้วย

ประเภทข้อมูลในตัวเพิ่มเติม ได้แก่ ทูเพิลneverยูเนียนและ: unknownvoidany

  • อาร์เรย์ที่มีชนิดข้อมูลที่กำหนดไว้ล่วงหน้าในแต่ละดัชนีเรียกว่าทูเปิล ซึ่งแสดงด้วยสัญลักษณ์ `<th> [type1, type2, ..., typeN]`
  • ตัวแปรที่สามารถเก็บข้อมูลได้มากกว่าหนึ่งประเภทเรียกว่า ยูเนียน ซึ่งแสดงด้วย|สัญลักษณ์ตรรกะ OR ( string | number)
  • ประเภท นี้neverใช้เมื่อประเภทที่กำหนดนั้นไม่น่าจะสร้างขึ้นได้ ซึ่งมีประโยชน์สำหรับการกรองประเภทที่แมปไว้
  • ประเภท นี้unknownใช้เมื่อจัดการกับข้อมูลที่มีรูปร่างไม่แน่นอน ต่างจาก ประเภท anyอื่น ตัวแปรunknownประเภท จะทำให้เกิดข้อผิดพลาดในการคอมไพล์เมื่อพยายามเข้าถึงคุณสมบัติหรือเมธอดบนตัวแปรนั้นโดยไม่ได้จำกัดประเภทให้แคบลงจนเป็นที่รู้จักก่อน ประเภทนี้มักใช้สำหรับการดักจับข้อผิดพลาด การจัดการการตอบสนอง API หรือข้อมูลที่ผู้ใช้ป้อน[ 29 ]
  • ชนิด นี้voidใช้เพื่อแสดงถึงการไม่มีชนิดข้อมูล เช่น จากฟังก์ชันที่ไม่มีreturnคำสั่งใดๆ
  • ค่าของประเภทanyรองรับการดำเนินการเช่นเดียวกับค่าใน JavaScript และมีการตรวจสอบประเภทคงที่ขั้นต่ำ[ 30 ]ซึ่งทำให้เหมาะสำหรับโครงสร้างที่มีประเภทอ่อนหรือแบบไดนามิก โดยทั่วไปแล้วไม่ควรใช้วิธีนี้และควรหลีกเลี่ยงเมื่อเป็นไปได้[ 31 ]

สามารถส่งออกคำอธิบายประเภทไปยังไฟล์ประกาศ แยกต่างหาก เพื่อให้ข้อมูลประเภทพร้อมใช้งานสำหรับ สคริปต์ TypeScript ที่ใช้ประเภทที่คอมไพล์ไว้ใน JavaScript แล้ว สามารถประกาศคำอธิบายประเภทสำหรับไลบรารี JavaScript ที่มีอยู่แล้วได้ เช่นเดียวกับที่ทำในNode.jsและjQuery

คอมไพเลอร์ TypeScript ใช้การอนุมานประเภทเมื่อไม่ได้ระบุประเภทไว้ ตัวอย่างเช่นaddเมธอดในโค้ดด้านบนจะถูกอนุมานว่าส่งคืนค่าnumberแม้ว่าจะไม่ได้ระบุคำอธิบายประเภทการส่งคืนไว้ก็ตาม ทั้งนี้ขึ้นอยู่กับประเภทคงที่ของleftและrightที่เป็นnumberและความรู้ของคอมไพเลอร์ที่ว่าผลลัพธ์ของการบวก สอง ตัวเข้าด้วย กัน numberจะเป็น เสมอnumber

หากไม่สามารถอนุมานประเภทได้เนื่องจากไม่มีการประกาศ (เช่นในโมดูล JavaScript ที่ไม่มีประเภท) ระบบจะใช้anyประเภทไดนามิกเป็นค่าเริ่มต้น สามารถระบุประเภทโมดูลเพิ่มเติมได้โดยใช้ไฟล์ประกาศ .d.ts โดยใช้declare module "moduleName"ไวยากรณ์ดังต่อไปนี้

ไฟล์ประกาศ

เมื่อคอมไพล์สคริปต์ TypeScript จะมีตัวเลือกในการสร้างไฟล์ประกาศ (ที่มีนามสกุล .exe .d.ts) ซึ่งทำหน้าที่เป็นอินเทอร์เฟซสำหรับส่วนประกอบต่างๆ ใน ​​JavaScript ที่คอมไพล์แล้ว ในกระบวนการนี้ คอมไพเลอร์จะตัดส่วนเนื้อหาของฟังก์ชันและเมธอดทั้งหมดออก และคงไว้เฉพาะลายเซ็นของประเภทที่ถูกส่งออกเท่านั้น ไฟล์ประกาศที่ได้สามารถนำไปใช้เพื่ออธิบายประเภทเสมือน TypeScript ที่ส่งออกของไลบรารีหรือโมดูล JavaScript เมื่อนักพัฒนาบุคคลที่สามนำไปใช้จาก TypeScript

แนวคิดของไฟล์ประกาศนั้นคล้ายคลึงกับแนวคิดของไฟล์ส่วนหัวที่พบในภาษา C/C ++

ประกาศnamespace Arithmetics { add ( left : number , right : number ) : number ; subtract ( left : number , right : number ) : number ; multiply ( left : number , right : number ) : number ; divide ( left : number , right : number ) : number ; }

ไฟล์ประกาศประเภทสามารถเขียนขึ้นเองได้สำหรับไลบรารี JavaScript ที่มีอยู่แล้ว ดังเช่นที่เคยทำมาแล้วสำหรับ jQuery และ Node.js

DefinitelyTypedเป็น คลังเก็บไฟล์ประกาศจำนวนมากสำหรับไลบรารี JavaScript ยอดนิยมต่างๆ ซึ่งจัดเก็บไว้บน GitHub

ยาสามัญ

TypeScript รองรับ การ เขียนโปรแกรมทั่วไปโดยใช้ไวยากรณ์ที่คล้ายกับJava [ 32 ]ต่อไปนี้เป็นตัวอย่างของฟังก์ชันเอกลักษณ์[ 33 ]

ฟังก์ชันเอกลักษณ์< T > ( x : T ) : T { คืนค่าx ; }

เช่นเดียวกับGenerics ในภาษา Javaเราสามารถกำหนดขอบเขตให้กับพารามิเตอร์ประเภทได้:

ฟังก์ชันf < T extends string > ( x : T ) : void { // ... }function prop < T , K extends keyof T > ( obj : T , key : K ) : T [ K ] { return obj [ key ]; }

นอกจากนี้ เช่นเดียวกับในภาษา C++ ก็สามารถกำหนดพารามิเตอร์เจเนริกเริ่มต้นได้เช่นกัน

ฟังก์ชันmakeArray < T = number > ( value : T ) : T [] { return [ value ]; }

ชั้นเรียน

TypeScript ใช้รูปแบบการระบุคำอธิบายประกอบแบบเดียวกันสำหรับเมธอดและฟิลด์ของคลาส เช่นเดียวกับฟังก์ชันและตัวแปรตามลำดับ เมื่อเปรียบเทียบกับคลาส JavaScript ทั่วไป คลาส TypeScript ยังสามารถใช้งานอินเทอร์เฟซผ่านimplementsคีย์เวิร์ด ใช้พารามิเตอร์ทั่วไปได้คล้ายกับJavaและระบุฟิลด์สาธารณะและส่วนตัวได้อีก ด้วย

คลาสPerson { สาธารณะname : string ; ส่วนตัวage : number ; ส่วนตัวsalary : number ;ตัวสร้าง( ชื่อ: สตริง, อายุ: ตัวเลข, เงินเดือน: ตัวเลข) { this.name = name ; this.age = age ; this.salary = salary ; }toString ( ) : string { return ` $ { this.name } ( $ { this.age } ) ( $ { this.salary } ) ` ; } }

ประเภทสหภาพ

TypeScript รองรับประเภท Union [ 34 ]ค่าต่างๆ จะถูก "ติดแท็ก" ด้วยประเภทโดยปริยายโดยภาษา และสามารถเรียกได้โดยใช้typeofการเรียกสำหรับค่าพื้นฐานและinstanceofการเปรียบเทียบสำหรับประเภทข้อมูลที่ซับซ้อน ประเภทที่มีการใช้งานทับซ้อนกัน (เช่น เมธอด slice มีอยู่ในทั้งสตริงและอาร์เรย์ ตัวดำเนินการบวกทำงานได้ทั้งกับสตริงและตัวเลข) ไม่จำเป็นต้องจำกัดเพิ่มเติมเพื่อใช้คุณสมบัติเหล่านี้

ฟังก์ชันsuccessor ( n : number | bigint ) : number | bigint { // ชนิดข้อมูลที่รองรับการดำเนินการเดียวกันไม่จำเป็นต้องลดขนาดreturn ++ n ; }ฟังก์ชันdependsOnParameter ( v : string | string [] | number ) { // ประเภทที่แตกต่างกันจำเป็นต้องจำกัดขอบเขตหาก( v instanceof Array ) { // ทำบางอย่าง} else if ( typeof ( v ) === "string" ) { // ทำอย่างอื่น} else { // ต้องเป็นตัวเลข} }

ประเภทแจงนับ

TypeScript เพิ่มชนิดข้อมูล 'enum' ให้กับ JavaScript

enum CardSuit { Clubs , Diamonds , Hearts , Spades };var c : CardSuit = CardSuit.Diamonds ;

โดยค่าเริ่มต้น enum จะกำหนดหมายเลขสมาชิกเริ่มต้นที่ 0 ซึ่งสามารถเปลี่ยนแปลงได้โดยการกำหนดค่าให้กับสมาชิกตัวแรก:

enum CardSuit { Clubs = 1 , Diamonds , Hearts , Spades };var c : CardSuit = CardSuit.Diamonds ;

สามารถตั้งค่าทุกอย่างได้:

enum CardSuit { Clubs = 1 , Diamonds = 2 , Hearts = 4 , Spades = 8 };var c : CardSuit = CardSuit.Diamonds ;

TypeScript รองรับการแมปค่าตัวเลขกับชื่อของมัน ตัวอย่างเช่น โค้ดนี้จะค้นหาชื่อของค่า 2:

enum CardSuit { Clubs = 1 , Diamonds , Hearts , Spades };var suitName : string = CardSuit [ 2 ];แจ้งเตือน( suitName );

โมดูลและเนมสเปซ

TypeScript แยกความแตกต่างระหว่างโมดูลและเนมสเปซ คล้ายกับโมดูลใน C++คุณสมบัติทั้งสองใน TypeScript รองรับการห่อหุ้มคลาส อินเทอร์เฟซ ฟังก์ชัน และตัวแปรลงในคอนเทนเนอร์ เนมสเปซ (เดิมคือโมดูลภายใน) ใช้การแสดงออกของฟังก์ชัน JavaScript ที่เรียกใช้ทันทีเพื่อห่อหุ้มโค้ด ในขณะที่โมดูล (เดิมคือโมดูลภายนอก) ใช้รูปแบบไลบรารี JavaScript ที่มีอยู่ ( CommonJSหรือ ES Modules) [ 35 ]

การจัดการทรัพยากร

แม้ว่า TypeScript จะไม่มีการจัดการหน่วยความจำด้วยตนเอง แต่ก็มีการจัดการทรัพยากรที่คล้ายกับusingบล็อก -with-resource ในC#หรือtryบล็อก -with-resources ในJavaหรือ การได้มาซึ่งทรัพยากรใน C++ คือการเริ่มต้นซึ่งจะปิดทรัพยากรโดยอัตโนมัติโดยไม่จำเป็นต้องใช้finallyบล็อก ใน TypeScript หากต้องการปิดอ็อบเจ็กต์โดยอัตโนมัติ จะต้องใช้งานอินเทอร์เฟซส่วนกลางDisposableและใช้งานเมธอดSymbol.dispose()ซึ่งจะถูกเรียกโดยอัตโนมัติเมื่อสิ้นสุดขอบเขต[ 28 ]

import * as fs from 'fs' ;คลาสTempFile implements Disposable { #path : string ; #handle : number ;constructor ( path : string ) { this . #path = path ; this . #handle = fs . openSync ( path , "w+" ); }เขียน( ข้อมูล: สตริง) : void { fs.writeSync ( this . # handle , data ) ; }[ Symbol.dispose ] ( ) : void { fs.closeSync ( this . # handle ) ; fs.unlinkSync ( this . # path ) ; } }ส่งออกฟังก์ชันdoSomeWork () { โดยใช้ไฟล์: TempFile = new TempFile ( ".some_temp_file.txt" );ถ้า( เงื่อนไขบางอย่าง) { // ทำอะไรบางอย่างตรงนี้} }

ดูเพิ่มเติม

อ่านเพิ่มเติม

  • Danny Goodman: JavaScript Bible , Wiley, John & Sons, ISBN 0-7645-3342-8.
  • เดวิด แฟลนาแกน, พอลล่า เฟอร์กูสัน: JavaScript: คู่มือฉบับสมบูรณ์ , O'Reilly & Associates, ISBN 0-596-10199-6.
  • Thomas A. Powell, Fritz Schneider: JavaScript: The Complete Reference , McGraw-Hill Companies, ISBN 0-07-219127-9.
  • Axel Rauschmayer: Speaking An In-Depth Guide for Programmers , 460 หน้า, O'Reilly Media, 25 กุมภาพันธ์ 2014, ISBN 978-1449365035( ฉบับออนไลน์ฟรี )
  • Emily Vander Veer: JavaScript For Dummies, ฉบับที่ 4 , Wiley, ISBN 0-7645-7659-3.
  • การแนะนำ JavaScript อีกครั้ง - ศูนย์พัฒนาซอฟต์แวร์ของ Mozilla
  • ลูป JavaScript
  • เอกสารอ้างอิงมาตรฐาน ECMAScript: ECMA-262
  • บทเรียน JavaScript แบบโต้ตอบ - เน้นตัวอย่าง
  • การฝึกอบรม JavaScript
  • เอกสารอ้างอิงหลักของ Mozilla Developer Center สำหรับ JavaScript เวอร์ชัน1.5 , 1.4 , 1.3และ1.2
  • เอกสารประกอบภาษา JavaScript ของ Mozilla
ดึงข้อมูลมาจาก " https://en.wikipedia.org/w/index.php?title=JavaScript_syntax&oldid=1360759124 "

สรุปเนื้อหา

ข้อมูลสำคัญจากบทความ

ข้อมูลสำคัญเกี่ยวกับ ไวยากรณ์ JavaScript

ไวยากรณ์ของJavaScriptคือชุดของกฎที่กำหนดโครงสร้างที่ถูกต้องของโปรแกรม JavaScript

ต้นกำเนิด

Brendan Eich สรุปที่มาของไวยากรณ์ในย่อหน้าแรกของข้อกำหนด JavaScript 1.1 [ 1 ] [ 2 ] ดังนี้:

คำสำคัญ

คำต่อไปนี้เป็นคำหลักและไม่สามารถใช้เป็นคำระบุตัวตนได้ในทุกกรณี

การคำนึงถึงตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก

JavaScript เป็น ภาษาที่คำนึงถึงตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก โดยทั่วไปแล้ว ชื่อของ คอนสตรัคเตอร์ มักจะขึ้นต้น ด้วย ตัวอักษรพิมพ์ ใหญ่ และชื่อของฟังก์ชันหรือตัวแปรจะขึ้นต้นด้วยตัวอักษรพิมพ์เล็ก