6 คุณสมบัติ JavaScript ที่คุณควรรู้

เผยแพร่แล้ว: 2020-09-24

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

วันนี้ฉันจะแสดงให้คุณเห็นหกคุณสมบัติ JavaScript ที่ยอดเยี่ยมจริงๆ โอเปอเรเตอร์ การกำหนดขอบเขตตัวแปร คำสัญญา ฟังก์ชันอะซิงโครนัส... คุณพร้อมหรือยังที่จะเรียนรู้สิ่งเหล่านี้ทั้งหมด

#1 ตัวเลือกการโยงใน JavaScript กับโอเปอเรเตอร์ ?.

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

 const toni = { name: 'Antonio', details: { age: 35, }, };

ในการเข้าถึง age ของ toni คุณต้องเข้าถึงแอตทริบิวต์ details ก่อนแล้วจึงค่อย age :

 function getAge( person ) { return person.details.age; }

ปัญหาที่เรามีในฟังก์ชันก่อนหน้านี้ และฉันแน่ใจว่าไม่ใช่เรื่องใหม่สำหรับคุณ นั่นคือคุณสมบัติที่เราคาดหวังให้ person มีไม่ได้อยู่ที่นั่นเสมอไป นั่นคือถ้าทั้ง person หรือ person.details undefined ฟังก์ชันด้านบนจะทำให้เกิดข้อผิดพลาดประเภท:

 getAge( toni ); // 35 getAge( {} ); // Uncaught TypeError: person.details is undefined

โดยปกติ เราจะแก้ไขปัญหานี้โดยเพิ่มเจ้าหน้าที่รักษาความปลอดภัยสองสามคน:

 function getAge( person ) { if ( ! person ) { return; } if ( ! person.details ) { return; } return person.details.age; } getAge( toni ); // 35 getAge( {} ); // undefined

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

 function getAge( person ) { return person?.details?.age; } getAge( toni ); // 35 getAge( {} ); // undefined

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

# 2 Nullish Coalescing Operator ( ?? )

ใน JavaScript มันง่ายมากที่จะตั้งค่าเริ่มต้นให้กับตัวแปรโดยใช้ตัวดำเนินการนี้: || , ขวา? ผิด! เราได้ทำสิ่งนี้มาหมดแล้ว แต่อาจส่งผลให้เกิดผลข้างเคียงที่ไม่คาดคิดได้ ถ้าคุณไม่ระวัง...

ตัวอย่างเช่น สมมติว่าเรามีตัวเลือกในร้านค้า Redux ที่ช่วยให้เราสามารถดึงค่าที่ผู้ใช้ตั้งไว้ หากผู้ใช้ยังไม่ได้ระบุค่า (นั่นคือ ค่านั้น undefined ) เราจะคืนค่าเริ่มต้นโดยใช้ || :

 function getValue( state ) { return state.value || 5; }

ตอนนี้ มาดูตัวอย่างบางส่วนของสิ่งที่เราจะได้รับจากฟังก์ชันก่อนหน้าหลังจากที่ผู้ใช้ตั้งค่าอย่างใดอย่างหนึ่ง:

 // No setValue( x )... getValue(); // 5 setValue( 2 ); getValue(); // 2 setValue( 1 ); getValue(); // 1 setValue( 0 ); getValue(); // 5

อ๊ะ! ทุกอย่างทำงานได้ดีจนกระทั่งเราไปถึงกรณีสุดท้าย! เห็นได้ชัดว่า หากผู้ใช้ตั้งค่าเป็น 0 ผลลัพธ์ของฟังก์ชันจะกลายเป็น 5 ทำไม? เหตุผลนั้นค่อนข้างไม่น่าเชื่อถือ: x||y จะคืนค่า y ถ้าหาก x เป็นค่า "เท็จ" เท่านั้น ซึ่งมักจะใช้ได้ดี เนื่องจาก undefined เป็นค่าเท็จ แต่ก็เป็น false หรือ 0 ตัวอย่างเช่น

ในความเป็นจริง เราต้องการตั้งค่า default เมื่อไม่มีเท่านั้น ดังนั้นเราจึงสามารถเพิ่มการป้องกันเพื่อตรวจสอบว่ามีค่าหรือไม่:

 function getValue( state ) { if ( undefined === state.value ) return 5; return state.value; }

และเรายังสามารถเขียนมันโดยใช้ตัวดำเนินการ ternary หากเรารู้สึกว่า:

 function getValue( state ) { return undefined === state.value ? 5 : state.value; }

แต่อีกครั้ง โซลูชันทั้งสองทำให้โค้ดซับซ้อนโดยไม่จำเป็น ในการกำหนดค่าเริ่มต้นให้กับตัวแปร เราต้องใช้ตัวดำเนินการการรวมเป็นโมฆะ ?? ซึ่งส่งคืนส่วนที่ถูกต้องหากและเฉพาะในกรณีที่ส่วนซ้ายเป็น null หรือ undefined :

 function getValue( state ) { return state.value ?? 5; }

และเซอร์ไพรส์ เซอร์ไพรส์! ผลลัพธ์คือสิ่งที่เราต้องการ:

 // No setValue( x )... getValue(); // 5 setValue( 2 ); getValue(); // 2 setValue( 1 ); getValue(); // 1 setValue( 0 ); getValue(); // 0

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

 value = value ?? 5;

เทียบเท่ากับสิ่งนี้:

 value ??= 5;

#3 คำสัญญาและฟังก์ชันแบบอะซิงโครนัส

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

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

 jQuery.ajax( { url: 'https://server.com/wp-json/wp/users/1', success: ( user ) => { console.log( user ); }, } );

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

 jQuery.ajax( { url: 'https://server.com/wp-json/wp/v2/users/1', success: ( user1 ) => { jQuery.ajax( { url: 'https://server.com/wp-json/wp/v2/users/2', success: ( user2 ) => { console.log( user1, user2 ); }, } ); }, } );

คำมั่นสัญญาคือทางออกของปัญหานี้: หากการได้รับผลลัพธ์บางอย่างไม่ได้เกิดขึ้นทันที (เช่น เมื่อเราดึงข้อมูลบางอย่างจากเซิร์ฟเวอร์) เราสามารถส่งคืนคำสัญญาของ JavaScript ได้ทันที วัตถุนี้เป็นตัวห่อหุ้มมูลค่าที่แท้จริงและหมายถึง "สัญญา" ที่มูลค่าดังกล่าวจะพร้อมใช้งานในอนาคต

ตัวอย่างเช่น หากเราต้องเขียนตัวอย่างแรกของเราโดยใช้คำสัญญา จะมีลักษณะดังนี้:

 const promise = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/1', } ); promise.then( ( user ) => console.log( user ) );

อย่างที่คุณเห็น wp.apiFetch ต้องดึงผู้ใช้ 1 จากเซิร์ฟเวอร์ แต่มันให้ผลลัพธ์ทันที อย่างไรก็ตาม ผลลัพธ์ไม่ใช่ตัวผู้ใช้เอง แต่เป็นคำสัญญาที่จะแก้ไขให้กับผู้ใช้เมื่อคำขอเสร็จสิ้น ดังนั้น ทั้งหมดที่เราต้องทำคือเขียนการติดต่อกลับที่จะประมวลผลการตอบสนองของสัญญาเมื่อได้รับการแก้ไข

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

 const promise1 = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/1', } ); const promise2 = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/2', } ); Promise.all( [ promise1, promise2 ] ).then( ( [ user1, user2 ] ) => console.log( user1, user2 ); );

เมื่อใช้คำสัญญา เราสามารถเรียกใช้คำขอคู่ขนานสองคำขอเพื่อเรียกข้อมูลผู้ใช้ 1 และ 2 และใช้ Promise.all เพื่อรอให้คำสัญญาทั้งสองได้รับการแก้ไข ไม่มีรหัสปาเก็ตตี้ที่มีการเรียกกลับที่ซ้อนกันที่เกี่ยวข้อง

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

 async function logTwoUsers( id1, id2 ) { const user1 = await wp.apiFetch( { url: '…' + id1 } ); const user2 = await wp.apiFetch( { url: '…' + id2 } ); console.log( user1, user2 ); }

เมื่อใดก็ตามที่คุณเรียกใช้การดำเนินการแบบอะซิงโครนัสภายในฟังก์ชันแบบอะซิงโครนัส คุณสามารถ await ผลลัพธ์ได้โดยใช้คีย์เวิร์ด wait สิ่งเดียวที่คุณควรจำไว้คือ เมื่อคุณกำหนดฟังก์ชัน async ผลลัพธ์จะเป็นคำสัญญาเสมอ:

 async function getNumberFive() { return 5; } const p = getNumberFive(); // a promise p.then( console.log ); // prints "5"

#4 ขอบเขตตัวแปรเมื่อใช้ let และ const

อย่างที่คุณรู้อยู่แล้ว ตอนนี้คุณสามารถประกาศตัวแปรได้โดยใช้คีย์เวิร์ด let และ const อดีตกำหนดตัวแปรและหลังกำหนดค่าคงที่:

 let x = 1; console.log( x ); // 1 x = 2; console.log( x ); // 2 const y = 1; console.log( y ); // 1 y = 2; // Uncaught TypeError: invalid assignment to const 'y' console.log( y ); // 1

คุณอาจคิดว่า let และ var เป็นสิ่งเดียวกัน เนื่องจากคีย์เวิร์ดทั้งสองช่วยให้เราประกาศตัวแปรที่ไม่คงที่ได้ แต่มีความแตกต่างอย่างมากระหว่างพวกเขา: ขอบเขตของพวกเขา ด้วย let และ const ขอบเขตของตัวแปรคือบล็อกที่กำหนดไว้ ใน var มันคือฟังก์ชันทั้งหมด

 function fn() { if ( true ) { var x = 1; let y = 2; const z = 3; }//end if console.log( x ); // 1 console.log( y ); // Uncaught ReferenceError: y is not defined console.log( z ); // Uncaught ReferenceError: z is not defined }

# 5 การแปลงข้อมูลเมื่อใช้ JSON.parse

ฟังก์ชัน JSON.parse แยกวิเคราะห์สตริง JSON และสร้างวัตถุ JavaScript ตัวอย่างเช่น:

 const x = JSON.parse( '{"x":1,"a":[1,2,3]}' ); // Object { x: 1, a: [ 1, 2, 3 ] }

สิ่งที่คนส่วนใหญ่ไม่รู้เกี่ยวกับมันคือรองรับอาร์กิวเมนต์ที่สองที่เรียกว่า reviver พารามิเตอร์นี้เป็นฟังก์ชันที่จะดำเนินการสำหรับแต่ละองค์ประกอบที่มีการแยกวิเคราะห์ ช่วยให้คุณจัดการค่าได้ตามต้องการ ตัวอย่างเช่น ลองนึกภาพสตริง JSON ดังต่อไปนี้:

 const json = '{"name":"David","birthday":"1985-12-01T10:00:00.000Z"}';

หากเราใช้ JSON.parse ตามที่เป็นอยู่ มันจะสร้างวัตถุที่มีแอตทริบิวต์สตริงสองรายการ: name และ birthday แต่ถ้าเราจัดเตรียมฟังก์ชัน reviver ให้กับ JSON.parse เราสามารถตรวจสอบให้แน่ใจว่า birthday ถูกแยกวิเคราะห์เป็น Date :

 const user = JSON.parse( json, ( key, value ) => 'birthday' === key ? new Date( value ) : value )

# 6 ตัวคั่นตัวเลขในซอร์สโค้ดโดยใช้อักขระ Undesrcore ( _ )

เคล็ดลับสุดท้ายของเราในวันนี้คือตัวคั่นตัวเลข มีข้อเสนอ (ขณะนี้อยู่ในขั้นที่ 4) ที่ทำให้สามารถเขียนตัวเลขในลักษณะที่ทำให้มนุษย์เข้าใจได้ง่ายขึ้น ตัวอย่างเช่น คุณบอกได้ไหมว่าตัวเลขต่อไปนี้มีขนาดใหญ่เพียงใด

 10000000000 2189719.25

ถ้าเราสามารถใช้ตัวคั่นหลักพันได้ มันจะง่ายกว่ามากที่จะตีความ! และนั่นคือสิ่งที่เราทำได้โดยใช้ขีดล่าง _ :

 10_000_000_000 2_189_719.25

สรุป

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

ภาพเด่นโดย Sam Dan Truong บน Unsplash