From b1bd294b88af063e7937a3659242a4680c4965c5 Mon Sep 17 00:00:00 2001 From: Prasit Tongpradit Date: Mon, 1 Apr 2024 21:08:12 +0700 Subject: [PATCH 1/5] =?UTF-8?q?=E0=B8=99=E0=B8=B4=E0=B8=9E=E0=B8=88?= =?UTF-8?q?=E0=B8=99=E0=B9=8C=E0=B8=9F=E0=B8=B1=E0=B8=87=E0=B8=81=E0=B9=8C?= =?UTF-8?q?=E0=B8=8A=E0=B8=B1=E0=B8=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../16-function-expressions/article.md | 357 ++---------------- 1 file changed, 39 insertions(+), 318 deletions(-) diff --git a/1-js/02-first-steps/16-function-expressions/article.md b/1-js/02-first-steps/16-function-expressions/article.md index f414efdd6..4f1985832 100644 --- a/1-js/02-first-steps/16-function-expressions/article.md +++ b/1-js/02-first-steps/16-function-expressions/article.md @@ -1,99 +1,95 @@ -# Function Expression +# นิพจน์ฟังก์ชัน -ในภาษา JavaScript ฟังก์ชันไม่ใช่แค่ "โครงสร้างภาษาที่พิเศษ" แต่ยังเป็นชนิดข้อมูลพิเศษอีกด้วย +ใน JavaScript ฟังก์ชันไม่ใช่ "โครงสร้างพิเศษทางภาษา" แต่เป็นค่าชนิดหนึ่งที่มีลักษณะเฉพาะ -ไวยากรณ์ที่เราเคยใช้มาก่อนหน้านี้เรียกว่า _Function Declaration_: +รูปแบบที่เราใช้ก่อนหน้านี้เรียกว่า *การประกาศฟังก์ชัน* (Function Declaration): ```js function sayHi() { - alert("สวัสดี"); + alert( "Hello" ); } ``` -นอกจากนี้ยังมีอีกรูปแบบหนึ่งในการสร้างฟังก์ชัน นั่นคือ _Function Expression_ +มีอีกวิธีหนึ่งในการสร้างฟังก์ชันที่เรียกว่า *นิพจน์ฟังก์ชัน* (Function Expression) -Function Expression ช่วยให้เราสามารถสร้างฟังก์ชันใหม่ได้ระหว่างนิพจน์ (expression) ใดๆ +ซึ่งช่วยให้เราสามารถสร้างฟังก์ชันใหม่ได้ในทุกๆ นิพจน์ (expression) ตัวอย่างเช่น: ```js let sayHi = function() { - alert("สวัสดี"); + alert( "Hello" ); }; ``` -ในที่นี้ เราจะเห็นว่าตัวแปร `sayHi` ได้รับการกำหนดค่าให้เป็นฟังก์ชันใหม่ ซึ่งถูกสร้างขึ้นมาเป็น `function() { alert("สวัสดี"); }` +ในที่นี้เราเห็นตัวแปร `sayHi` ได้รับค่าเป็นฟังก์ชันใหม่ที่สร้างขึ้นด้วย `function() { alert("Hello"); }` -เนื่องจากการสร้างฟังก์ชันนี้เกิดขึ้นในบริบทของนิพจน์กำหนดค่า (ทางขวาของเครื่องหมาย `=`) จึงเรียกว่าเป็น _Function Expression_ +เนื่องจากการสร้างฟังก์ชันเกิดขึ้นในบริบทของนิพจน์การกำหนดค่า (ทางขวาของเครื่องหมาย `=`) จึงเป็นนิพจน์ฟังก์ชัน -สังเกตได้ว่า ไม่มีการระบุชื่อต่อท้ายคีย์เวิร์ด `function` ซึ่งการละชื่อนี้สามารถทำได้กับ Function Expression +โปรดสังเกตว่าไม่มีชื่อหลังคำสำคัญ `function` การละเว้นชื่อนั้นอนุญาตสำหรับนิพจน์ฟังก์ชัน -ในตัวอย่างนี้ เรากำหนดค่าให้กับตัวแปรทันที นั่นหมายความว่า "สร้างฟังก์ชันขึ้นมาแล้วกำหนดลงในตัวแปร `sayHi`" +ในที่นี้เรากำหนดค่าให้กับตัวแปรทันที ดังนั้นความหมายของตัวอย่างโค้ดเหล่านี้จึงเหมือนกันคือ "สร้างฟังก์ชันและเก็บลงในตัวแปร `sayHi`" -ในสถานการณ์ที่ซับซ้อนกว่าซึ่งจะได้เจอในภายหลัง ฟังก์ชันอาจจะถูกสร้างและเรียกใช้งานทันที หรือถูกกำหนดเวลาให้รันภายหลัง โดยไม่จำเป็นต้องเก็บไว้ในตัวแปร ดังนั้นจึงมักจะไม่ระบุชื่อให้กับฟังก์ชันเหล่านี้ +ในสถานการณ์ที่ซับซ้อนขึ้นซึ่งเราจะเจอในภายหลัง ฟังก์ชันอาจถูกสร้างขึ้นและเรียกใช้ทันที หรือกำหนดเวลาเพื่อใช้ในภายหลัง โดยไม่เก็บไว้ที่ใดเลย จึงไม่มีชื่อ (anonymous) -## ฟังก์ชันก็คือค่าชนิดหนึ่ง +## ฟังก์ชันคือค่า -ขอย้ำอีกครั้งว่า ไม่ว่าจะสร้างฟังก์ชันด้วยวิธีใด มันก็ยังคงเป็นค่า (value) อยู่วันยังค่ำ ในทั้งสองตัวอย่างข้างต้น เราเก็บฟังก์ชันไว้ในตัวแปร `sayHi` +ขอย้ำอีกครั้ง: ไม่ว่าฟังก์ชันจะถูกสร้างมาอย่างไร มันคือค่าชนิดหนึ่ง ตัวอย่างทั้งสองด้านบนเก็บฟังก์ชันไว้ในตัวแปร `sayHi` -เราสามารถแสดงค่าของฟังก์ชันออกมาด้วยคำสั่ง `alert` ได้เลย: +เราสามารถแสดงค่านั้นผ่าน `alert` ได้ด้วย: ```js run function sayHi() { - alert("สวัสดี"); + alert( "Hello" ); } *!* -alert(sayHi); // แสดงโค้ดฟังก์ชัน +alert( sayHi ); // แสดงโค้ดฟังก์ชัน */!* ``` -สังเกตว่าบรรทัดสุดท้ายไม่ได้เรียกใช้ฟังก์ชัน เพราะไม่มีวงเล็บ `()` ต่อท้ายชื่อฟังก์ชัน `sayHi` ในบางภาษา การอ้างถึงชื่อฟังก์ชันอย่างเดียวจะเท่ากับการเรียกใช้มัน แต่ในจาวาสคริปต์ไม่เป็นเช่นนั้น +โปรดสังเกตว่าบรรทัดสุดท้ายไม่ได้เรียกใช้ฟังก์ชัน เพราะไม่มีวงเล็บหลัง `sayHi` มีภาษาโปรแกรมบางภาษาที่เมื่อพูดถึงชื่อฟังก์ชันจะทำให้เกิดการเรียกใช้ทันที แต่ JavaScript ไม่เป็นเช่นนั้น -ในจาวาสคริปต์ ฟังก์ชันถือเป็นค่าประเภทหนึ่ง เราจึงสามารถจัดการมันได้เหมือนกับค่าชนิดอื่นๆ ในโค้ดด้านบน เราแปลงค่าของฟังก์ชันเป็นสตริง ซึ่งก็คือโค้ดต้นฉบับของฟังก์ชันนั่นเอง +ใน JavaScript ฟังก์ชันเป็นค่าประเภทหนึ่ง เราจึงสามารถจัดการกับมันเหมือนกับค่าประเภทอื่นๆ โค้ดด้านบนแสดงการแปลงเป็นสตริง ซึ่งก็คือซอร์สโค้ดนั่นเอง -แน่นอนว่าฟังก์ชันเป็นค่าที่พิเศษกว่าค่าปกติทั่วไป ตรงที่เราสามารถเรียกใช้งานมันได้ เช่น `sayHi()` +แน่นอนว่าฟังก์ชันเป็นค่าพิเศษ ตรงที่เราสามารถเรียกใช้มันได้ เช่น `sayHi()` -แต่ถึงอย่างนั้น มันก็ยังคงความเป็นค่าชนิดหนึ่งอยู่ เราจึงสามารถจัดการมันได้เหมือนกับค่าประเภทอื่นๆ +แต่มันก็ยังคงเป็นค่าอยู่ เราจึงทำงานกับมันได้เหมือนกับค่าประเภทอื่นๆ -เราสามารถคัดลอกฟังก์ชันไปใส่ในตัวแปรอื่นได้: +เราสามารถคัดลอกฟังก์ชันไปยังตัวแปรอื่นได้: ```js run no-beautify -function sayHi() { // (1) สร้าง - alert("สวัสดี"); +function sayHi() { // (1) สร้าง + alert( "Hello" ); } -let func = sayHi; // (2) คัดลอก +let func = sayHi; // (2) คัดลอก -func(); // สวัสดี // (3) เรียกใช้ฟังก์ชันที่คัดลอกมา (ทำงานได้)! - -sayHi(); // สวัสดี // เรียกใช้ฟังก์ชันต้นฉบับก็ยังทำได้ +func(); // Hello // (3) เรียกใช้สำเนา (ใช้ได้)! +sayHi(); // Hello // ตัวต้นฉบับยังใช้ได้เหมือนเดิม (แน่นอน) ``` -มาดูว่าเกิดอะไรขึ้นในรายละเอียด: - -1. Function Declaration `(1)` สร้างฟังก์ชันและเก็บไว้ในตัวแปร `sayHi` - -2. บรรทัด `(2)` คัดลอกฟังก์ชันไปไว้ในตัวแปร `func` สังเกตว่าไม่มีวงเล็บ `()` ต่อท้ายชื่อ `sayHi` เพราะถ้ามี จะกลายเป็นเขียน _ผลลัพธ์_ จากการเรียก `sayHi()` ไปเก็บใน `func` ไม่ใช่เขียน _ฟังก์ชัน_ `sayHi` เอง +นี่คือสิ่งที่เกิดขึ้นในรายละเอียด: -3. ตอนนี้ฟังก์ชันก็ถูกเรียกได้ทั้งในชื่อ `sayHi()` และ `func()` +1. การประกาศฟังก์ชัน `(1)` สร้างฟังก์ชันและเก็บไว้ในตัวแปรชื่อ `sayHi` +2. บรรทัด `(2)` คัดลอกมันไปยังตัวแปร `func` โปรดสังเกตอีกครั้ง: ไม่มีวงเล็บหลัง `sayHi` ถ้ามี `func = sayHi()` จะเขียน *ผลลัพธ์จากการเรียกใช้* `sayHi()` ลงใน `func` ไม่ใช่เขียน *ฟังก์ชัน* `sayHi` เอง +3. ตอนนี้ฟังก์ชันสามารถเรียกได้ทั้งในชื่อ `sayHi()` และ `func()` -หรือเราอาจจะใช้ Function Expression ตั้งแต่ต้นก็ได้: +เราสามารถใช้นิพจน์ฟังก์ชันเพื่อประกาศ `sayHi` ในบรรทัดแรกก็ได้: ```js let sayHi = function() { // (1) สร้าง - alert("สวัสดี"); + alert( "Hello" ); }; let func = sayHi; // ... ``` -ทุกอย่างก็ยังทำงานได้เหมือนเดิม +ทุกอย่างจะทำงานเหมือนเดิม -```smart header="ทำไมถึงมีเครื่องหมายอัฒภาคต่อท้าย?" - -คุณอาจสงสัยว่าทำไม Function Expression ถึงมีเครื่องหมายอัฒภาค `;` ต่อท้าย ส่วน Function Declaration ไม่มี: +```smart header="ทำไมต้องมีเครื่องหมายอัฒภาคตามหลัง?" +คุณอาจสงสัยว่าทำไมนิพจน์ฟังก์ชันถึงต้องมีเครื่องหมายอัฒภาค `;` ท้ายประโยค แต่การประกาศฟังก์ชันไม่ต้องมี: ```js function sayHi() { @@ -105,282 +101,7 @@ let sayHi = function() { }*!*;*/!* ``` -คำตอบคือ เพราะ Function Expression ถูกสร้างภายในคำสั่งกำหนดค่าเป็น `function(...) {...}`: `let sayHi = ...;` ซึ่งจริงๆ แล้วเครื่องหมายอัฒภาค `;` เป็นสิ่งที่แนะนำให้ใส่ต่อท้ายคำสั่ง แต่ไม่ได้เป็นส่วนหนึ่งของไวยากรณ์ฟังก์ชัน - -ถ้าเป็นการกำหนดค่าแบบง่ายๆ เช่น `let sayHi = 5;` ก็ควรมีเครื่องหมายอัฒภาคอยู่ด้วย รวมถึงตอนกำหนดฟังก์ชันก็เช่นกัน -```` - -## ฟังก์ชันคอลแบ็ก - -มาดูตัวอย่างเพิ่มเติมของการส่งฟังก์ชันเป็นค่าและการใช้ Function Expression กัน - -เราจะลองเขียนฟังก์ชัน `ask(question, yes, no)` ที่รับพารามิเตอร์ 3 ตัว: - -`question` -: ข้อความคำถาม - -`yes` -: ฟังก์ชันที่จะทำงานเมื่อคำตอบคือ "ใช่" - -`no` -: ฟังก์ชันที่จะทำงานเมื่อคำตอบคือ "ไม่" - -ฟังก์ชันนี้จะถามคำถาม `question` และเรียกใช้ `yes()` หรือ `no()` ขึ้นอยู่กับคำตอบที่ได้รับจากผู้ใช้: - -```js run -*!* -function ask(question, yes, no) { - if (confirm(question)) yes() - else no(); -} -*/!* - -function showOk() { - alert("คุณเห็นด้วย"); -} - -function showCancel() { - alert("คุณยกเลิก"); -} - -// วิธีเรียกใช้: ส่งฟังก์ชัน showOk, showCancel เป็นอาร์กิวเมนต์ให้ ask -ask("คุณเห็นด้วยไหม?", showOk, showCancel); -``` - -ในทางปฏิบัติ ฟังก์ชันแบบนี้ใช้ประโยชน์ได้มาก ความต่างหลักระหว่างฟังก์ชัน `ask` ในโลกจริงกับตัวอย่างด้านบนคือ ในโลกจริงฟังก์ชันมักใช้การโต้ตอบกับผู้ใช้ที่ซับซ้อนกว่า `confirm` ธรรมดา โดยเฉพาะในเบราว์เซอร์ที่ฟังก์ชันพวกนี้มักจะแสดงหน้าต่างคำถามที่สวยงาม แต่เรื่องนั้นเป็นอีกประเด็นหนึ่ง - -**อาร์กิวเมนต์ `showOk` และ `showCancel` ของฟังก์ชัน `ask` เรียกว่า *ฟังก์ชันคอลแบ็ก* หรือเรียกสั้นๆ ว่า *คอลแบ็ก*** - -ไอเดียหลักๆ คือเราส่งฟังก์ชันไปเป็นค่า แล้วหวังว่ามันจะถูก "เรียกกลับมา" ในภายหลังเมื่อจำเป็น ในกรณีนี้ `showOk` กลายเป็นคอลแบ็กสำหรับคำตอบ "ใช่" และ `showCancel` สำหรับคำตอบ "ไม่" - -เราสามารถเขียนโค้ดให้สั้นลงด้วยการใช้ Function Expression: - -```js run no-beautify -function ask(question, yes, no) { - if (confirm(question)) yes() - else no(); -} - -*!* -ask( - "คุณเห็นด้วยไหม?", - function() { alert("คุณเห็นด้วย"); }, - function() { alert("คุณยกเลิก"); } -); -*/!* -``` - -ตรงนี้ฟังก์ชันถูกประกาศไว้โดยตรงภายในการเรียกใช้ `ask(...)` โดยไม่มีการตั้งชื่อ เรียกว่าฟังก์ชันแบบ *ไม่ระบุชื่อ (anonymous)* ฟังก์ชันเหล่านี้จะเข้าถึงจากภายนอก `ask` ไม่ได้ (เพราะไม่ได้ผูกกับตัวแปรใด) แต่ในกรณีนี้เราก็ไม่ต้องการให้มันเข้าถึงได้อยู่แล้ว - -โค้ดในลักษณะนี้มักจะเห็นได้บ่อยๆ ในสคริปต์ของพวกเรา ถือเป็นไปตามสไตล์การเขียนแบบ JavaScript - -```smart header="ฟังก์ชันคือค่าที่ใช้ในการแทน \"การกระทำ\"" -โดยปกติแล้ว ค่าอย่างสตริงหรือตัวเลขจะใช้แทน *ข้อมูล* - -ส่วนฟังก์ชันนั้น สามารถมองได้ว่าเป็น *การกระทำ* - -เราสามารถส่งมันเป็นค่าไปมาในตัวแปร และเรียกใช้มันได้เมื่อไหร่ก็ได้ที่ต้องการ -``` - -## Function Expression กับ Function Declaration - -มาสรุปความแตกต่างหลักระหว่าง Function Declaration และ Function Expression กัน - -ก่อนอื่น มาดูที่ไวยากรณ์: วิธีแยกแยะสองอย่างนี้ในโค้ด - -- *Function Declaration:* ฟังก์ชันที่ประกาศเป็นคำสั่งแยกเดี่ยวในโฟลว์หลักของโค้ด: - - ```js - // Function Declaration - function sum(a, b) { - return a + b; - } - ``` -- *Function Expression:* ฟังก์ชันที่ถูกสร้างขึ้นภายในนิพจน์หรือโครงสร้างไวยากรณ์อื่นๆ ในตัวอย่างนี้ ฟังก์ชันถูกสร้างขึ้นทางด้านขวาของ "นิพจน์กำหนดค่า" `=`: - - ```js - // Function Expression - let sum = function(a, b) { - return a + b; - }; - ``` - -ความแตกต่างที่ลึกซึ้งกว่านั้นคือ *เวลา* ที่ฟังก์ชันถูกสร้างขึ้นโดยเอ็นจิ้น JavaScript - -**Function Expression จะถูกสร้างขึ้นเมื่อการทำงานมาถึงบรรทัดนั้น และใช้ได้ตั้งแต่ตอนนั้นเป็นต้นไปเท่านั้น** - -เมื่อการประมวลผลไปถึงด้านขวาของการกำหนดค่า `let sum = function…` ตอนนี้ไงล่ะ ฟังก์ชันจะถูกสร้างขึ้น และสามารถนำไปใช้ได้ (เช่น กำหนดค่าให้ตัวแปร เรียกใช้งาน เป็นต้น) ตั้งแต่จุดนี้เป็นต้นไป - -ในขณะที่ Function Declaration นั้นแตกต่างออกไป - -**Function Declaration สามารถเรียกใช้ได้ก่อนที่จะมีการประกาศมันเสียอีก** - -ยกตัวอย่างเช่น Function Declaration ที่อยู่ในระดับโกลบอลจะมองเห็นได้ทั่วทั้งสคริปต์ ไม่ว่ามันจะถูกประกาศไว้ตรงไหนก็ตาม - -นั่นเป็นเพราะกระบวนการภายใน ตอนที่ JavaScript เตรียมจะรันสคริปต์ มันจะค้นหา Function Declaration ในระดับโกลบอลก่อน แล้วสร้างฟังก์ชันเหล่านั้นขึ้น เราอาจมองเรียกมันว่า "ขั้นตอนเตรียมการ" - -หลังจากที่ Function Declaration ทั้งหมดถูกประมวลผลเสร็จแล้ว การทำงานของโค้ดจึงเริ่มต้นขึ้น ดังนั้นจึงสามารถเข้าถึงฟังก์ชันเหล่านี้ได้ทันที - -ดังเช่นตัวอย่างนี้ที่ทำงานได้: - -```js run refresh untrusted -*!* -sayHi("John"); // Hello, John -*/!* - -function sayHi(name) { - alert( `Hello, ${name}` ); -} -``` - -Function Declaration `sayHi` จะถูกสร้างขึ้นตอนที่ JavaScript เตรียมจะเริ่มรันสคริปต์ และจะมองเห็นได้ทั่วทั้งสคริปต์ - -...แต่ถ้าเป็น Function Expression มันจะไม่สามารถทำงานแบบนี้ได้: - -```js run refresh untrusted -*!* -sayHi("John"); // เกิด error! -*/!* - -let sayHi = function(name) { // (*) ไม่มีเวทย์มนต์อีกต่อไป - alert( `Hello, ${name}` ); -}; -``` - -Function Expression จะถูกสร้างขึ้นเมื่อการทำงานมาถึงบรรทัดนั้น ซึ่งในที่นี้ก็คือบรรทัด `(*)` ซึ่งมันสายไปเสียแล้ว - -อีกหนึ่งคุณสมบัติพิเศษของ Function Declaration คือขอบเขตของบล็อก - -**ในโหมดเข้มงวด ถ้า Function Declaration อยู่ภายในบล็อกโค้ด มันจะมองเห็นได้ทั่วทั้งภายในบล็อกนั้น แต่จะมองไม่เห็นจากภายนอกบล็อก** - -ยกตัวอย่างเช่น สมมติเราต้องการประกาศฟังก์ชัน `welcome()` โดยขึ้นอยู่กับตัวแปร `age` ที่ได้มาตอน runtime และวางแผนจะใช้มันภายหลัง - -ถ้าเราใช้ Function Declaration มันจะไม่ทำงานตามที่คาดหวัง: - -```js run -let age = prompt("What is your age?", 18); - -// ประกาศฟังก์ชันแบบมีเงื่อนไข -if (age < 18) { - - function welcome() { - alert("Hello!"); - } - -} else { - - function welcome() { - alert("Greetings!"); - } - -} - -// ...วางแผนจะใช้ในภายหลัง -*!* -welcome(); // เกิด Error: welcome is not defined -*/!* -``` - -นั่นเป็นเพราะว่า Function Declaration จะมองเห็นได้เฉพาะภายในบล็อกโค้ดที่ประกาศมันเท่านั้น - -ลองดูตัวอย่างอื่นอีก: - -```js run -let age = 16; // สมมติใช้ 16 เป็นตัวอย่าง - -if (age < 18) { -*!* - welcome(); // \ (ทำงานได้) -*/!* - // | - function welcome() { // | Function Declaration พร้อมใช้งาน - alert("Hello!"); // | ได้ทุกที่ภายในบล็อกที่ประกาศมัน - } // | - // | -*!* - welcome(); // / (ทำงานได้) -*/!* - -} else { - - function welcome() { - alert("Greetings!"); - } -} - -// ตอนนี้เราอยู่นอกวงเล็บปีกกาแล้ว -// ดังนั้นจึงมองไม่เห็น Function Declaration ที่ประกาศภายในวงเล็บ - -*!* -welcome(); // เกิด Error: welcome is not defined -*/!* -``` - -แล้วจะทำอย่างไรให้ `welcome` มองเห็นได้จากภายนอก `if` ล่ะ? - -วิธีที่ถูกต้องคือใช้ Function Expression แล้วกำหนดค่า `welcome` ให้กับตัวแปรที่ประกาศไว้ภายนอก `if` ซึ่งจะทำให้มองเห็นได้อย่างถูกต้อง - -ดังเช่นโค้ดนี้ที่ทำงานได้ตามที่ตั้งใจ: - -```js run -let age = prompt("What is your age?", 18); - -let welcome; - -if (age < 18) { - - welcome = function() { - alert("Hello!"); - }; - -} else { - - welcome = function() { - alert("Greetings!"); - }; - -} - -*!* -welcome(); // ตอนนี้ ok แล้ว -*/!* -``` - -หรือจะทำให้เรียบง่ายยิ่งขึ้นโดยใช้ตัวดำเนินการ `?`: - -```js run -let age = prompt("What is your age?", 18); - -let welcome = (age < 18) ? - function() { alert("Hello!"); } : - function() { alert("Greetings!"); }; - -*!* -welcome(); // ตอนนี้ ok แล้ว -*/!* -``` - - -```smart header="เมื่อไหร่ควรเลือกใช้ Function Declaration กับ Function Expression?" -โดยทั่วไปแล้ว ถ้าเป็นไปได้ควรเลือกใช้ Function Declaration มันให้อิสระในการจัดระเบียบโค้ดมากกว่า เพราะเราสามารถเรียกฟังก์ชันพวกนี้ได้ก่อนที่จะประกาศมัน - -นอกจากนี้ยังทำให้โค้ดอ่านง่ายขึ้นด้วย เพราะการมองหา `function f(…) {…}` ในโค้ดนั้นง่ายกว่า `let f = function(…) {…};` Function Declaration จะ "เด่น" กว่านั่นเอง - -...แต่ถ้า Function Declaration ไม่เหมาะกับเราด้วยเหตุผลบางอย่าง หรือถ้าเราอยากประกาศฟังก์ชันแบบมีเงื่อนไข (อย่างในตัวอย่างที่เราเห็นไปเมื่อกี้) การใช้ Function Expression ก็จะเหมาะสมกว่า -``` - -## สรุป - -- ฟังก์ชันคือค่าชนิดหนึ่ง สามารถกำหนดค่า คัดลอก หรือประกาศไว้ในตำแหน่งใดๆ ของโค้ดก็ได้ - -- ถ้าฟังก์ชันถูกประกาศเป็นคำสั่งแยกเดี่ยวในโฟลว์หลักของโค้ด จะเรียกว่า "Function Declaration" - -- ถ้าฟังก์ชันถูกสร้างขึ้นเป็นส่วนหนึ่งของนิพจน์ จะเรียกว่า "Function Expression" - -- Function Declaration จะถูกประมวลผลก่อนที่บล็อกโค้ดจะเริ่มทำงาน ทำให้มองเห็นได้ทั่วทั้งบล็อก - -- Function Expression จะถูกสร้างขึ้นเมื่อลำดับการทำงานมาถึงบรรทัดนั้น - -ในกรณีส่วนใหญ่ที่เราต้องการประกาศฟังก์ชัน การใช้ Function Declaration จะเป็นตัวเลือกที่ดีกว่า เพราะมันมองเห็นได้ก่อนที่จะถูกประกาศ ทำให้เรามีความยืดหยุ่นในการจัดวางโค้ดมากขึ้น และมักจะอ่านเข้าใจได้ง่ายกว่า +คำตอบคือ: นิพจน์ฟังก์ชันถูกสร้างขึ้นในรูปแบบ `function(…) {…}` ภายในประโยคการกำหนดค่า: `let sayHi = …;` ควรมีเครื่องหมายอัฒภาค `;` ท้ายประโยค มันไม่ใช่ส่วนหนึ่งของไวยากรณ์ฟังก์ชัน -ดังนั้น เราควรใช้ Function Expression ก็ต่อเมื่อ Function Declaration ไม่ตอบโจทย์งานของเรา ซึ่งเราได้เห็นตัวอย่างสองสามกรณีไปแล้วในบทนี้ และจะเห็นเพิ่มเติมอีกในอนาคต \ No newline at end of file +เครื่องหมายอัฒภาคจะอยู่ในการกำหนดค่าทั่วไป เช่น `let sayHi = 5;` และอยู่ในการกำหนดค่าฟังก์ชันเช่นกัน +``` \ No newline at end of file From acd0b548a28d4844bd8f59bb2b94a3f43af40b9d Mon Sep 17 00:00:00 2001 From: Prasit Tongpradit Date: Mon, 1 Apr 2024 21:15:58 +0700 Subject: [PATCH 2/5] =?UTF-8?q?=E0=B8=9F=E0=B8=B1=E0=B8=87=E0=B8=81?= =?UTF-8?q?=E0=B9=8C=E0=B8=8A=E0=B8=B1=E0=B8=99=E0=B8=84=E0=B8=AD=E0=B8=A5?= =?UTF-8?q?=E0=B9=81=E0=B8=9A=E0=B9=87=E0=B8=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../16-function-expressions/article.md | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/1-js/02-first-steps/16-function-expressions/article.md b/1-js/02-first-steps/16-function-expressions/article.md index 4f1985832..aaab0ed2b 100644 --- a/1-js/02-first-steps/16-function-expressions/article.md +++ b/1-js/02-first-steps/16-function-expressions/article.md @@ -104,4 +104,75 @@ let sayHi = function() { คำตอบคือ: นิพจน์ฟังก์ชันถูกสร้างขึ้นในรูปแบบ `function(…) {…}` ภายในประโยคการกำหนดค่า: `let sayHi = …;` ควรมีเครื่องหมายอัฒภาค `;` ท้ายประโยค มันไม่ใช่ส่วนหนึ่งของไวยากรณ์ฟังก์ชัน เครื่องหมายอัฒภาคจะอยู่ในการกำหนดค่าทั่วไป เช่น `let sayHi = 5;` และอยู่ในการกำหนดค่าฟังก์ชันเช่นกัน + +## ฟังก์ชันคอลแบ็ก + +มาดูตัวอย่างเพิ่มเติมเกี่ยวกับการส่งฟังก์ชันเป็นค่า และการใช้นิพจน์ฟังก์ชันกัน + +เราจะเขียนฟังก์ชัน `ask(question, yes, no)` ที่มีสามพารามิเตอร์: + +`question` +: ข้อความของคำถาม + +`yes` +: ฟังก์ชันที่จะรันหากคำตอบคือ "ใช่" + +`no` +: ฟังก์ชันที่จะรันหากคำตอบคือ "ไม่" + +ฟังก์ชันควรถาม `question` และเรียกใช้ `yes()` หรือ `no()` ตามคำตอบของผู้ใช้: + +```js run +*!* +function ask(question, yes, no) { + if (confirm(question)) yes() + else no(); +} +*/!* + +function showOk() { + alert( "You agreed." ); +} + +function showCancel() { + alert( "You canceled the execution." ); +} + +// การใช้งาน: ส่งฟังก์ชัน showOk, showCancel เป็นอาร์กิวเมนต์ให้ ask +ask("Do you agree?", showOk, showCancel); +``` + +ในทางปฏิบัติ ฟังก์ชันเหล่านี้มีประโยชน์มาก ความแตกต่างหลักระหว่าง `ask` ในชีวิตจริงกับตัวอย่างข้างต้นคือ ฟังก์ชันในชีวิตจริงใช้วิธีที่ซับซ้อนกว่าในการโต้ตอบกับผู้ใช้ นอกเหนือจากการใช้ `confirm` ธรรมดา ในเบราว์เซอร์ ฟังก์ชันเหล่านี้มักสร้างหน้าต่างคำถามที่สวยงาม แต่นั่นเป็นอีกเรื่องหนึ่ง + +**อาร์กิวเมนต์ `showOk` และ `showCancel` ของ `ask` เรียกว่า *ฟังก์ชันคอลแบ็ก* หรือ *คอลแบ็ก*** + +แนวคิดคือ เราส่งฟังก์ชันไป และคาดหวังว่ามันจะถูก "เรียกกลับ (called back)" ในภายหลังหากจำเป็น ในกรณีของเรา `showOk` เป็นคอลแบ็กสำหรับคำตอบ "ใช่" และ `showCancel` สำหรับคำตอบ "ไม่" + +เราสามารถใช้นิพจน์ฟังก์ชันเพื่อเขียนฟังก์ชันเทียบเท่าที่สั้นกว่าได้: + +```js run no-beautify +function ask(question, yes, no) { + if (confirm(question)) yes() + else no(); +} + +*!* +ask( + "Do you agree?", + function() { alert("You agreed."); }, + function() { alert("You canceled the execution."); } +); +*/!* +``` + +ในที่นี้ ฟังก์ชันถูกประกาศขึ้นภายในการเรียก `ask(...)` โดยตรง โดยไม่มีการระบุชื่อ จึงเรียกว่า *anonymous (ไม่มีชื่อ)* ฟังก์ชันเหล่านี้ไม่สามารถเข้าถึงได้จากภายนอกของ `ask` (เพราะไม่ได้กำหนดให้กับตัวแปร) แต่นั่นแหละคือสิ่งที่เราต้องการในที่นี้ + +โค้ดลักษณะนี้ปรากฏในสคริปต์ของเราได้อย่างเป็นธรรมชาติ มันเป็นไปตามหลักการของภาษา JavaScript + +```smart header="ฟังก์ชันคือค่าที่แทนการ \"กระทำ\"" +ค่าปกติ เช่น สตริงหรือตัวเลข แสดงถึง *ข้อมูล* + +สามารถมองฟังก์ชันเป็น *การกระทำ* ได้ + +เราสามารถส่งผ่านมันไประหว่างตัวแปร และสั่งให้ทำงานเมื่อใดก็ได้ที่ต้องการ ``` \ No newline at end of file From 992b82888fb215a31c34ee0bf7d4adfa71a603a1 Mon Sep 17 00:00:00 2001 From: Prasit Tongpradit Date: Mon, 1 Apr 2024 21:23:58 +0700 Subject: [PATCH 3/5] =?UTF-8?q?Function=20Expression=20=E0=B8=81=E0=B8=B1?= =?UTF-8?q?=E0=B8=9A=20Function=20Declaration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../16-function-expressions/article.md | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/1-js/02-first-steps/16-function-expressions/article.md b/1-js/02-first-steps/16-function-expressions/article.md index aaab0ed2b..33bfda129 100644 --- a/1-js/02-first-steps/16-function-expressions/article.md +++ b/1-js/02-first-steps/16-function-expressions/article.md @@ -175,4 +175,103 @@ ask( สามารถมองฟังก์ชันเป็น *การกระทำ* ได้ เราสามารถส่งผ่านมันไประหว่างตัวแปร และสั่งให้ทำงานเมื่อใดก็ได้ที่ต้องการ +``` + +## Function Expression กับ Function Declaration + +มาสรุปความแตกต่างสำคัญระหว่าง Function Declaration และ Function Expression กัน + +ประการแรก ในแง่วากยสัมพันธ์: วิธีแยกแยะทั้งสองแบบในโค้ด + +- *Function Declaration:* ฟังก์ชันที่ประกาศเป็นประโยคแยกต่างหาก ในเนื้อหาหลักของโค้ด: + + ```js + // Function Declaration + function sum(a, b) { + return a + b; + } + ``` +- *Function Expression:* ฟังก์ชันที่ถูกสร้างภายในนิพจน์ หรือภายในโครงสร้างไวยากรณ์อื่นๆ ในที่นี้ ฟังก์ชันถูกสร้างขึ้นทางด้านขวาของ "นิพจน์การกำหนดค่า" `=`: + + ```js + // Function Expression + let sum = function(a, b) { + return a + b; + }; + ``` + +ความแตกต่างที่ละเอียดอ่อนกว่าคือ เวลาที่ฟังก์ชันถูกสร้างโดยเอนจินของ JavaScript *เมื่อใด* + +**Function Expression ถูกสร้างเมื่อการประมวลผลมาถึงมัน และใช้งานได้ตั้งแต่จุดนั้นเป็นต้นไป** + +เมื่อโฟลว์การประมวลผลผ่านไปถึงทางด้านขวาของการกำหนดค่า `let sum = function…` -- ฟังก์ชันก็จะถูกสร้างขึ้น และสามารถใช้งานได้ตั้งแต่ตอนนี้เป็นต้นไป (กำหนดค่า เรียกใช้ ฯลฯ) + +Function Declaration นั้นแตกต่างออกไป + +**Function Declaration สามารถเรียกใช้ได้ก่อนที่จะมีการประกาศ** + +ยกตัวอย่างเช่น Function Declaration ระดับโกลบอลจะมองเห็นได้ทั่วทั้งสคริปต์ ไม่ว่าจะอยู่ตรงไหน + +นั่นเป็นเพราะอัลกอริทึมภายใน เมื่อ JavaScript เตรียมตัวที่จะรันสคริปต์ มันจะมองหา Function Declaration ระดับโกลบอลก่อนเป็นอันดับแรก แล้วทำการสร้างฟังก์ชันเหล่านั้นขึ้น เราอาจมองเป็น "ขั้นตอนการเตรียมการ" + +และหลังจากประมวลผล Function Declaration ทั้งหมดแล้ว จึงค่อยประมวลผลโค้ดตามปกติ ดังนั้นโค้ดจึงสามารถเข้าถึงฟังก์ชันเหล่านั้นได้ + +ตัวอย่างเช่น โค้ดนี้สามารถทำงานได้: + +```js run refresh untrusted +*!* +sayHi("John"); // Hello, John +*/!* + +function sayHi(name) { + alert( `Hello, ${name}` ); +} +``` + +Function Declaration `sayHi` ถูกสร้างขึ้นตอนที่ JavaScript กำลังเตรียมจะเริ่มสคริปต์ และมองเห็นได้ทั่วทั้งสคริปต์ + +...แต่ถ้าเป็น Function Expression ก็จะใช้งานไม่ได้: + +```js run refresh untrusted +*!* +sayHi("John"); // error! +*/!* + +let sayHi = function(name) { // (*) ไม่มีเวทมนต์อีกต่อไป + alert( `Hello, ${name}` ); +}; +``` + +Function Expression จะถูกสร้างก็ต่อเมื่อการประมวลผลมาถึงมัน ซึ่งจะเกิดขึ้นที่บรรทัด `(*)` เท่านั้น ช้าไปแล้ว + +อีกคุณสมบัติพิเศษของ Function Declaration คือขอบเขตแบบบล็อก + +**ในโหมดเข้มงวด เมื่อ Function Declaration อยู่ภายในบล็อกโค้ด มันจะมองเห็นได้ทั่วภายในบล็อกนั้น แต่มองไม่เห็นภายนอกบล็อก** + +ยกตัวอย่าง สมมติเราต้องการประกาศฟังก์ชัน `welcome()` โดยขึ้นอยู่กับค่าตัวแปร `age` ที่ได้มาระหว่างรันไทม์ และเราวางแผนจะใช้มันในภายหลัง + +หากใช้ Function Declaration มันจะไม่ทำงานตามที่ตั้งใจ: + +```js run +let age = prompt("What is your age?", 18); + +// ประกาศฟังก์ชันตามเงื่อนไข +if (age < 18) { + + function welcome() { + alert("Hello!"); + } + +} else { + + function welcome() { + alert("Greetings!"); + } + +} + +// ...ใช้ในภายหลัง +*!* +welcome(); // Error: welcome is not defined +*/!* ``` \ No newline at end of file From e1b1de90e82e401b3741b0ba97a2cdea2625308b Mon Sep 17 00:00:00 2001 From: Prasit Tongpradit Date: Mon, 1 Apr 2024 21:28:10 +0700 Subject: [PATCH 4/5] =?UTF-8?q?=E0=B8=AA=E0=B8=A3=E0=B8=B8=E0=B8=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../16-function-expressions/article.md | 67 ++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/1-js/02-first-steps/16-function-expressions/article.md b/1-js/02-first-steps/16-function-expressions/article.md index 33bfda129..0e0973d96 100644 --- a/1-js/02-first-steps/16-function-expressions/article.md +++ b/1-js/02-first-steps/16-function-expressions/article.md @@ -274,4 +274,69 @@ if (age < 18) { *!* welcome(); // Error: welcome is not defined */!* -``` \ No newline at end of file +``` + +เราจะทำอย่างไรเพื่อให้ `welcome` มองเห็นได้จากภายนอก `if`? + +วิธีที่ถูกต้องคือการใช้ Function Expression และกำหนดค่า `welcome` ให้กับตัวแปรที่ประกาศไว้นอก `if` ซึ่งมีการมองเห็นที่เหมาะสม + +โค้ดนี้ทำงานตามที่ตั้งใจไว้: + +```js run +let age = prompt("What is your age?", 18); + +let welcome; + +if (age < 18) { + + welcome = function() { + alert("Hello!"); + }; + +} else { + + welcome = function() { + alert("Greetings!"); + }; + +} + +*!* +welcome(); // ตอนนี้ใช้ได้แล้ว +*/!* +``` + +หรือเราสามารถทำให้มันเรียบง่ายขึ้นอีกโดยใช้ตัวดำเนินการเครื่องหมายคำถาม `?`: + +```js run +let age = prompt("What is your age?", 18); + +let welcome = (age < 18) ? + function() { alert("Hello!"); } : + function() { alert("Greetings!"); }; + +*!* +welcome(); // ตอนนี้ใช้ได้แล้ว +*/!* +``` + + +```smart header="เมื่อไหร่ควรเลือกใช้ Function Declaration หรือ Function Expression?" +โดยหลักการทั่วไป เมื่อเราต้องการประกาศฟังก์ชัน สิ่งแรกที่ควรพิจารณาคือใช้ไวยากรณ์แบบ Function Declaration เพราะมันให้อิสระในการจัดวางโค้ดมากกว่า เนื่องจากเราสามารถเรียกใช้ฟังก์ชันเหล่านั้นได้ก่อนที่จะมีการประกาศ + +นอกจากนี้ยังอ่านทำความเข้าใจง่ายกว่า เพราะมองหา `function f(…) {…}` ในโค้ดได้ง่ายกว่า `let f = function(…) {…};` Function Declaration นั้น "โดดเด่นมากกว่า" + +...แต่ถ้า Function Declaration ไม่เหมาะสมกับเราด้วยเหตุผลบางประการ หรือเราต้องการประกาศแบบมีเงื่อนไข (เราเพิ่งเห็นตัวอย่างไป) ควรใช้ Function Expression แทน +``` + +## สรุป + +- ฟังก์ชันคือค่า สามารถกำหนดค่า คัดลอก หรือประกาศไว้ที่ใดก็ได้ในโค้ด +- ถ้าฟังก์ชันถูกประกาศเป็นประโยคแยกต่างหากในลำดับการทำงานหลักของโค้ด เรียกว่า "Function Declaration" +- ถ้าฟังก์ชันถูกสร้างขึ้นเป็นส่วนหนึ่งของนิพจน์ เรียกว่า "Function Expression" +- Function Declaration จะถูกประมวลผลก่อนที่บล็อกโค้ดจะเริ่มทำงาน ทำให้มองเห็นได้ทั่วทั้งบล็อก +- Function Expression จะถูกสร้างขึ้นเมื่อลำดับการทำงานมาถึงจุดที่มันอยู่ + +ในเกือบทุกกรณีที่เราต้องการประกาศฟังก์ชัน Function Declaration เป็นตัวเลือกที่เหมาะสมกว่า เพราะมันมองเห็นได้ก่อนการประกาศจริงๆ ทำให้เรามีความยืดหยุ่นในการจัดวางโค้ดมากขึ้น และมักจะอ่านเข้าใจง่ายกว่า + +ดังนั้นเราควรใช้ Function Expression เฉพาะเมื่อ Function Declaration ไม่เหมาะสมกับงาน เราได้เห็นตัวอย่างไปบ้างแล้วในบทนี้ และจะเห็นเพิ่มเติมในอนาคต \ No newline at end of file From fc403d616af871b84aab5ab99d48b816bb46102d Mon Sep 17 00:00:00 2001 From: Prasit Tongpradit Date: Mon, 1 Apr 2024 21:42:30 +0700 Subject: [PATCH 5/5] revise article.md --- .../16-function-expressions/article.md | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/1-js/02-first-steps/16-function-expressions/article.md b/1-js/02-first-steps/16-function-expressions/article.md index 0e0973d96..fdb59a607 100644 --- a/1-js/02-first-steps/16-function-expressions/article.md +++ b/1-js/02-first-steps/16-function-expressions/article.md @@ -177,24 +177,24 @@ ask( เราสามารถส่งผ่านมันไประหว่างตัวแปร และสั่งให้ทำงานเมื่อใดก็ได้ที่ต้องการ ``` -## Function Expression กับ Function Declaration +## นิพจน์ฟังก์ชัน (Function Expression) กับ การประกาศฟังก์ชัน (Function Declaration) -มาสรุปความแตกต่างสำคัญระหว่าง Function Declaration และ Function Expression กัน +มาสรุปความแตกต่างสำคัญระหว่างการประกาศฟังก์ชันและนิพจน์ฟังก์ชันกัน ประการแรก ในแง่วากยสัมพันธ์: วิธีแยกแยะทั้งสองแบบในโค้ด -- *Function Declaration:* ฟังก์ชันที่ประกาศเป็นประโยคแยกต่างหาก ในเนื้อหาหลักของโค้ด: +- *การประกาศฟังก์ชัน:* ฟังก์ชันที่ประกาศเป็นประโยคแยกต่างหาก ในเนื้อหาหลักของโค้ด: ```js - // Function Declaration + // การประกาศฟังก์ชัน function sum(a, b) { return a + b; } ``` -- *Function Expression:* ฟังก์ชันที่ถูกสร้างภายในนิพจน์ หรือภายในโครงสร้างไวยากรณ์อื่นๆ ในที่นี้ ฟังก์ชันถูกสร้างขึ้นทางด้านขวาของ "นิพจน์การกำหนดค่า" `=`: +- *นิพจน์ฟังก์ชัน:* ฟังก์ชันที่ถูกสร้างภายในนิพจน์ หรือภายในโครงสร้างไวยากรณ์อื่นๆ ในที่นี้ ฟังก์ชันถูกสร้างขึ้นทางด้านขวาของ "นิพจน์การกำหนดค่า" `=`: ```js - // Function Expression + // นิพจน์ฟังก์ชัน let sum = function(a, b) { return a + b; }; @@ -202,19 +202,19 @@ ask( ความแตกต่างที่ละเอียดอ่อนกว่าคือ เวลาที่ฟังก์ชันถูกสร้างโดยเอนจินของ JavaScript *เมื่อใด* -**Function Expression ถูกสร้างเมื่อการประมวลผลมาถึงมัน และใช้งานได้ตั้งแต่จุดนั้นเป็นต้นไป** +**นิพจน์ฟังก์ชัน ถูกสร้างเมื่อการประมวลผลมาถึงมัน และใช้งานได้ตั้งแต่จุดนั้นเป็นต้นไป** เมื่อโฟลว์การประมวลผลผ่านไปถึงทางด้านขวาของการกำหนดค่า `let sum = function…` -- ฟังก์ชันก็จะถูกสร้างขึ้น และสามารถใช้งานได้ตั้งแต่ตอนนี้เป็นต้นไป (กำหนดค่า เรียกใช้ ฯลฯ) -Function Declaration นั้นแตกต่างออกไป +การประกาศฟังก์ชันนั้นแตกต่างออกไป -**Function Declaration สามารถเรียกใช้ได้ก่อนที่จะมีการประกาศ** +**การประกาศฟังก์ชันสามารถเรียกใช้ได้ก่อนที่จะมีการประกาศ** -ยกตัวอย่างเช่น Function Declaration ระดับโกลบอลจะมองเห็นได้ทั่วทั้งสคริปต์ ไม่ว่าจะอยู่ตรงไหน +ยกตัวอย่างเช่น การประกาศฟังก์ชันระดับโกลบอลจะมองเห็นได้ทั่วทั้งสคริปต์ ไม่ว่าจะอยู่ตรงไหน -นั่นเป็นเพราะอัลกอริทึมภายใน เมื่อ JavaScript เตรียมตัวที่จะรันสคริปต์ มันจะมองหา Function Declaration ระดับโกลบอลก่อนเป็นอันดับแรก แล้วทำการสร้างฟังก์ชันเหล่านั้นขึ้น เราอาจมองเป็น "ขั้นตอนการเตรียมการ" +นั่นเป็นเพราะอัลกอริทึมภายใน เมื่อ JavaScript เตรียมตัวที่จะรันสคริปต์ มันจะมองหา การประกาศฟังก์ชันระดับโกลบอลก่อนเป็นอันดับแรก แล้วทำการสร้างฟังก์ชันเหล่านั้นขึ้น เราอาจมองเป็น "ขั้นตอนการเตรียมการ" -และหลังจากประมวลผล Function Declaration ทั้งหมดแล้ว จึงค่อยประมวลผลโค้ดตามปกติ ดังนั้นโค้ดจึงสามารถเข้าถึงฟังก์ชันเหล่านั้นได้ +และหลังจากประมวลผล การประกาศฟังก์ชันทั้งหมดแล้ว จึงค่อยประมวลผลโค้ดตามปกติ ดังนั้นโค้ดจึงสามารถเข้าถึงฟังก์ชันเหล่านั้นได้ ตัวอย่างเช่น โค้ดนี้สามารถทำงานได้: @@ -228,9 +228,9 @@ function sayHi(name) { } ``` -Function Declaration `sayHi` ถูกสร้างขึ้นตอนที่ JavaScript กำลังเตรียมจะเริ่มสคริปต์ และมองเห็นได้ทั่วทั้งสคริปต์ +การประกาศฟังก์ชัน `sayHi` ถูกสร้างขึ้นตอนที่ JavaScript กำลังเตรียมจะเริ่มสคริปต์ และมองเห็นได้ทั่วทั้งสคริปต์ -...แต่ถ้าเป็น Function Expression ก็จะใช้งานไม่ได้: +...แต่ถ้าเป็น นิพจน์ฟังก์ชันก็จะใช้งานไม่ได้: ```js run refresh untrusted *!* @@ -242,15 +242,15 @@ let sayHi = function(name) { // (*) ไม่มีเวทมนต์อี }; ``` -Function Expression จะถูกสร้างก็ต่อเมื่อการประมวลผลมาถึงมัน ซึ่งจะเกิดขึ้นที่บรรทัด `(*)` เท่านั้น ช้าไปแล้ว +นิพจน์ฟังก์ชันจะถูกสร้างก็ต่อเมื่อการประมวลผลมาถึงมัน ซึ่งจะเกิดขึ้นที่บรรทัด `(*)` เท่านั้น ช้าไปแล้ว -อีกคุณสมบัติพิเศษของ Function Declaration คือขอบเขตแบบบล็อก +อีกคุณสมบัติพิเศษของ การประกาศฟังก์ชันคือขอบเขตแบบบล็อก -**ในโหมดเข้มงวด เมื่อ Function Declaration อยู่ภายในบล็อกโค้ด มันจะมองเห็นได้ทั่วภายในบล็อกนั้น แต่มองไม่เห็นภายนอกบล็อก** +**ในโหมดเข้มงวด เมื่อการประกาศฟังก์ชันอยู่ภายในบล็อกโค้ด มันจะมองเห็นได้ทั่วภายในบล็อกนั้น แต่มองไม่เห็นภายนอกบล็อก** ยกตัวอย่าง สมมติเราต้องการประกาศฟังก์ชัน `welcome()` โดยขึ้นอยู่กับค่าตัวแปร `age` ที่ได้มาระหว่างรันไทม์ และเราวางแผนจะใช้มันในภายหลัง -หากใช้ Function Declaration มันจะไม่ทำงานตามที่ตั้งใจ: +หากใช้ การประกาศฟังก์ชันมันจะไม่ทำงานตามที่ตั้งใจ: ```js run let age = prompt("What is your age?", 18); @@ -321,12 +321,12 @@ welcome(); // ตอนนี้ใช้ได้แล้ว ``` -```smart header="เมื่อไหร่ควรเลือกใช้ Function Declaration หรือ Function Expression?" -โดยหลักการทั่วไป เมื่อเราต้องการประกาศฟังก์ชัน สิ่งแรกที่ควรพิจารณาคือใช้ไวยากรณ์แบบ Function Declaration เพราะมันให้อิสระในการจัดวางโค้ดมากกว่า เนื่องจากเราสามารถเรียกใช้ฟังก์ชันเหล่านั้นได้ก่อนที่จะมีการประกาศ +```smart header="เมื่อไหร่ควรเลือกใช้การประกาศฟังก์ชัน หรือนิพจน์ฟังก์ชัน?" +โดยหลักการทั่วไป เมื่อเราต้องการประกาศฟังก์ชัน สิ่งแรกที่ควรพิจารณาคือใช้ไวยากรณ์แบบการประกาศฟังก์ชัน เพราะมันให้อิสระในการจัดวางโค้ดมากกว่า เนื่องจากเราสามารถเรียกใช้ฟังก์ชันเหล่านั้นได้ก่อนที่จะมีการประกาศ -นอกจากนี้ยังอ่านทำความเข้าใจง่ายกว่า เพราะมองหา `function f(…) {…}` ในโค้ดได้ง่ายกว่า `let f = function(…) {…};` Function Declaration นั้น "โดดเด่นมากกว่า" +นอกจากนี้ยังอ่านทำความเข้าใจง่ายกว่า เพราะมองหา `function f(…) {…}` ในโค้ดได้ง่ายกว่า `let f = function(…) {…};` การประกาศฟังก์ชันนั้น "โดดเด่นมากกว่า" -...แต่ถ้า Function Declaration ไม่เหมาะสมกับเราด้วยเหตุผลบางประการ หรือเราต้องการประกาศแบบมีเงื่อนไข (เราเพิ่งเห็นตัวอย่างไป) ควรใช้ Function Expression แทน +...แต่ถ้าการประกาศฟังก์ชันไม่เหมาะสมกับเราด้วยเหตุผลบางประการ หรือเราต้องการประกาศแบบมีเงื่อนไข (เราเพิ่งเห็นตัวอย่างไป) ควรใช้นิพจน์ฟังก์ชันแทน ``` ## สรุป