ตัวแปร

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

ชื่อของตัวแปรเรียกว่าตัวระบุ ตัวระบุที่ถูกต้องต้องเป็นไปตามกฎต่อไปนี้

  • ตัวระบุอาจมีตัวอักษร Unicode, เครื่องหมายดอลลาร์ ($), อักขระขีดล่าง (_), ตัวเลข (0-9) และแม้แต่อักขระ Unicode บางตัว
  • ตัวระบุต้องไม่มีช่องว่าง เนื่องจากโปรแกรมแยกวิเคราะห์ใช้ช่องว่างเพื่อแยกองค์ประกอบอินพุต ตัวอย่างเช่น หากคุณพยายามเรียกตัวแปร my Variable แทน myVariable โปรแกรมแยกวิเคราะห์จะเห็นตัวระบุ 2 รายการ ได้แก่ my และ Variable และแสดงข้อผิดพลาดทางไวยากรณ์ ("โทเค็นที่ไม่คาดคิด: ตัวระบุ")
  • ตัวระบุต้องขึ้นต้นด้วยตัวอักษร เครื่องหมายขีดล่าง (_) หรือเครื่องหมายดอลลาร์ ($) ต้องไม่ขึ้นต้นด้วยตัวเลขเพื่อป้องกันความสับสนระหว่างตัวเลขกับตัวระบุ

    let 1a = true;
    
    > Uncaught SyntaxError: Invalid or unexpected token
    

    หาก JavaScript อนุญาตตัวเลขที่จุดเริ่มต้นของตัวระบุ ก็จะอนุญาตให้ใช้ตัวระบุที่ประกอบด้วยตัวเลขเท่านั้น ซึ่งจะทำให้เกิดความขัดแย้งระหว่างตัวเลขที่ใช้เป็นตัวเลขและตัวเลขที่ใช้เป็นตัวระบุ

    let 10 = 20
    
    10 + 5
    > ?
    
  • "คําที่สงวนไว้" ที่มีความหมายทางไวยากรณ์อยู่แล้วจะใช้เป็นตัวระบุไม่ได้

  • ตัวระบุต้องไม่มีสัญลักษณ์พิเศษ (! . , / \ + - * =)

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

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

let camelCasedIdentifier = true;

โปรเจ็กต์บางโปรเจ็กต์ใช้รูปแบบการตั้งชื่ออื่นๆ โดยขึ้นอยู่กับบริบทและลักษณะของข้อมูล เช่น โดยทั่วไปแล้วตัวอักษรแรกของคลาสจะเป็นตัวพิมพ์ใหญ่ ชื่อคลาสที่มีหลายคำจึงมักใช้รูปแบบ Camel Case ที่เรียกกันทั่วไปว่า "Upper Camel Case" หรือรูปแบบPascal

class MyClass {

}

ตัวระบุควรอธิบายลักษณะของข้อมูลที่เก็บไว้อย่างกระชับ (เช่น currentMonthDays เป็นชื่อที่ดีกว่า theNumberOfDaysInTheCurrentMonth) และอ่านได้ชัดเจนโดยย่อ (originalValue ดีกว่า val) ตัวระบุ myVariable ที่ใช้ตลอดทั้งโมดูลนี้ใช้ได้ในบริบทของตัวอย่างแบบแยกต่างหาก แต่จะไม่ค่อยมีประโยชน์ในโค้ดเวอร์ชันที่ใช้งานจริงเนื่องจากไม่ได้ให้ข้อมูลเกี่ยวกับข้อมูลที่เก็บไว้

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

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

การประกาศตัวแปร

มีหลายวิธีในการทําให้ JavaScript ทราบตัวระบุ ซึ่งเป็นกระบวนการที่เรียกว่า "การประกาศ" ตัวแปร ประกาศตัวแปรโดยใช้คีย์เวิร์ด let, const หรือ var

let myVariable;

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

เมื่อทํางานในโค้ดเบสสมัยใหม่ ให้ใช้ let แทน var var ยังใช้งานได้ในเบราว์เซอร์สมัยใหม่ แต่มีพฤติกรรมบางอย่างที่ใช้งานยากซึ่งกำหนดไว้ใน JavaScript เวอร์ชันแรกๆ และไม่สามารถเปลี่ยนแปลงได้ในภายหลังเพื่อรักษาความเข้ากันได้ย้อนหลัง let เพิ่มเข้ามาใน ES6 เพื่อแก้ไขปัญหาบางอย่างเกี่ยวกับการออกแบบ var

ตัวแปรที่ประกาศจะเริ่มต้นด้วยการกําหนดค่าให้กับตัวแปร ใช้เครื่องหมายเท่ากับ (=) ตัวเดียวเพื่อกําหนดหรือกําหนดค่าใหม่ให้กับตัวแปร คุณดำเนินการนี้เป็นส่วนหนึ่งของคำสั่งเดียวกันที่ประกาศได้

let myVariable = 5;

myVariable + myVariable
> 10

นอกจากนี้ คุณยังประกาศตัวแปรด้วย let (หรือ var) โดยไม่ต้องเริ่มต้นตัวแปรในทันทีได้ด้วย หากกำหนดค่าเริ่มต้น ค่าเริ่มต้นของตัวแปรจะเป็น undefined จนกว่าโค้ดจะกําหนดค่าให้

let myVariable;

myVariable;
> undefined

myVariable = 5;

myVariable + myVariable
> 10

ตัวแปรที่มีค่า undefined แตกต่างจากตัวแปรที่ไม่มีคําจํากัดความซึ่งยังไม่ได้ประกาศตัวระบุ การอ้างอิงตัวแปรที่คุณไม่ได้ประกาศจะทำให้เกิดข้อผิดพลาด

myVariable
> Uncaught ReferenceError: myVariable is not defined

let myVariable;

myVariable
> undefined

โดยทั่วไปการเชื่อมโยงตัวระบุกับค่าเรียกว่า "การเชื่อมโยง" ไวยากรณ์ที่อยู่หลังคีย์เวิร์ด let, var หรือ const เรียกว่า "รายการการเชื่อมโยง" และอนุญาตให้มีการประกาศตัวแปรหลายรายการที่คั่นด้วยคอมมา (ลงท้ายด้วยเซมิโคลอนตามที่คาดไว้) ซึ่งทําให้ข้อมูลโค้ดต่อไปนี้ทํางานเหมือนกัน

let firstVariable,
     secondVariable,
     thirdVariable;
let firstVariable;
let secondVariable;
let thirdVariable;

การกำหนดค่าตัวแปรใหม่จะไม่ใช้ let (หรือ var) เนื่องจาก JavaScript ทราบอยู่แล้วว่ามีตัวแปรอยู่

let myVariable = true;

myVariable
> true

myVariable = false;

myVariable
> false

คุณสามารถกําหนดค่าใหม่ให้กับตัวแปรโดยอิงตามค่าที่มีอยู่ได้ ดังนี้

let myVariable = 10;

myVariable
> 10

myVariable = myVariable * myVariable;

myVariable
> 100

หากคุณพยายามประกาศตัวแปรอีกครั้งโดยใช้ let ในสภาพแวดล้อมที่ใช้งานจริง คุณจะได้รับข้อผิดพลาดเกี่ยวกับไวยากรณ์

let myVariable = true;
let myVariable = false;
> Uncaught SyntaxError: redeclaration of let myVariable

เครื่องมือสําหรับนักพัฒนาซอฟต์แวร์ของเบราว์เซอร์จะอนุญาตการประกาศ let (และ class) อีกครั้งได้มากกว่า คุณจึงอาจไม่เห็นข้อผิดพลาดเดียวกันในคอนโซลนักพัฒนาซอฟต์แวร์

var อนุญาตให้ประกาศซ้ำโดยไม่จำเป็นเพื่อรักษาความเข้ากันได้กับเบราว์เซอร์รุ่นเดิม โดยจะไม่มีข้อผิดพลาดในบริบทใดๆ ดังนี้

var myVariable = true;
var myVariable = false;

myVariable\
> false

const

ใช้คีย์เวิร์ด const เพื่อประกาศค่าคงที่ ซึ่งเป็นตัวแปรประเภทหนึ่งที่ต้องมีการเริ่มต้นค่าทันทีและจะเปลี่ยนแปลงไม่ได้ ตัวระบุสำหรับค่าคงที่จะใช้กฎเดียวกันกับตัวแปรที่ประกาศโดยใช้ let (และ var) ดังนี้

const myConstant = true;

myConstant
> true

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

const myConstant;
Uncaught SyntaxError: missing = in const declaration

การพยายามเปลี่ยนค่าของตัวแปรที่ประกาศด้วย const ในลักษณะที่คุณอาจเปลี่ยนค่าของตัวแปรที่ประกาศด้วย let (หรือ var) จะทำให้เกิดข้อผิดพลาดประเภทนี้

const myConstant = true;

myConstant = false;
> Uncaught TypeError: invalid assignment to const 'myConstant'

อย่างไรก็ตาม เมื่อคонстантเชื่อมโยงกับออบเจ็กต์ พร็อพเพอร์ตี้ของออบเจ็กต์นั้นจะเปลี่ยนแปลงได้

const constantObject = { "firstvalue" : true };

constantObject
> Object { firstvalue: true }

constantObject.secondvalue = false;

constantObject
> Object { firstvalue: true, secondvalue: false }

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

const constantObject = { "firstvalue" : true };

constantObject = false
> Uncaught TypeError: invalid assignment to const 'constantObject'

เมื่อคุณไม่ต้องการให้มีการกําหนดตัวแปรใหม่ แนวทางปฏิบัติแนะนำคือให้ตัวแปรเป็นค่าคงที่ การใช้ const บอกให้ทีมพัฒนาซอฟต์แวร์หรือผู้ดูแลโปรเจ็กต์ในอนาคตอย่าเปลี่ยนแปลงค่านั้น เพื่อหลีกเลี่ยงการละเมิดสมมติฐานที่โค้ดของคุณทำเกี่ยวกับวิธีการใช้งาน เช่น ตัวแปรจะได้รับการประเมินตามประเภทข้อมูลที่คาดไว้ในที่สุด

ขอบเขตตัวแปร

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

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

ขอบเขตการบล็อก

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

{
    let scopedVariable = true;
    console.log( scopedVariable );
}
> true

scopedVariable
> ReferenceError: scopedVariable is not defined

ในแง่ของ JavaScript ตัวแปรระดับบล็อกไม่มีอยู่นอกบล็อกที่มีตัวแปรนั้น เช่น คุณสามารถประกาศค่าคงที่ภายในบล็อก แล้วประกาศค่าคงที่อีกรายการหนึ่งนอกบล็อกที่ใช้ตัวระบุเดียวกัน ดังนี้

{
  const myConstant = false;
}
const myConstant = true;

scopedConstant;
> true

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

{
    let scopedVariable = true;
    {
    console.log( scopedVariable );
    }
}
> true

ค่าของตัวแปรที่ประกาศไว้สามารถเปลี่ยนแปลงได้จากภายในบล็อกที่สืบทอด

{
    let scopedVariable = false;
    {
    scopedVariable = true;
    }
    console.log( scopedVariable );
}
> true

ตัวแปรใหม่สามารถเริ่มต้นด้วย let หรือ const ภายในบล็อกที่สืบทอดได้โดยไม่มีข้อผิดพลาด แม้ว่าจะใช้ตัวระบุเดียวกันกับตัวแปรในบล็อกหลักก็ตาม

{
    let scopedVariable = false;
    {
    let scopedVariable = true;
    }
    console.log( scopedVariable );
}
> false

ขอบเขตของฟังก์ชัน

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

function myFunction() {
    var scopedVariable = true;

    return scopedVariable;
}

scopedVariable;
> ReferenceError: scopedVariable is not defined

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

function myFunction() {
    var scopedVariable = true;

    return scopedVariable;
}

scopedVariable;
> ReferenceError: scopedVariable is not defined

myFunction();
> true

scopedVariable;
> ReferenceError: scopedVariable is not defined

ขอบเขตส่วนกลาง

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

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

ตัวแปรที่ประกาศโดยใช้ var นอกฟังก์ชันหลัก หรือใช้ let หรือ const นอกบล็อกหลักจะเป็นตัวแปรส่วนกลาง

var functionGlobal = true; // Global
let blockGlobal = true; // Global

{
    console.log( blockGlobal );
    console.log( functionGlobal );
}
> true
> true

(function() {
    console.log( blockGlobal );
    console.log( functionGlobal );
}());
> true
> true

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

function myFunction() {
    globalVariable = "global";

    return globalVariable
}

myFunction()\
> "global"

globalVariable\
> "global"

การยกแบบปรับได้

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

hoistedVariable
> undefined

var hoistedVariable;

เนื่องจากมีเพียงการประกาศตัวแปรเท่านั้นที่โฮสต์ ไม่ใช่การเริ่มต้นตัวแปร ระบบจะไม่ยกระดับตัวแปรที่ไม่ได้ประกาศอย่างชัดแจ้งด้วย var, let หรือ const

unhoistedVariable;
> Uncaught ReferenceError: unhoistedVariable is not defined

unhoistedVariable = true;

ดังที่ได้กล่าวไว้ก่อนหน้านี้ ระบบจะกําหนดค่า undefined ให้กับตัวแปรที่ประกาศไว้แต่ยังไม่ได้เริ่มต้น ลักษณะการทำงานดังกล่าวมีผลกับการประกาศตัวแปรที่ยกระดับด้วยเช่นกัน แต่มีผลเฉพาะกับตัวแปรที่ประกาศโดยใช้ var เท่านั้น

hoistedVariable
> undefined

var hoistedVariable = 2 + 2;

hoistedVariable\
> 4

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

let และ const จัดการลักษณะการทำงานนี้ด้วยการแสดงข้อผิดพลาดเมื่อมีการเข้าถึงตัวแปรก่อนที่จะสร้าง

{
    hoistedVariable;

    let hoistedVariable;
}
> Uncaught ReferenceError: can't access lexical declaration 'hoistedVariable' before initialization

ข้อผิดพลาดนี้แตกต่างจากข้อผิดพลาด "hoistedVariable is not defined" ที่คุณอาจพบเมื่อพยายามเข้าถึงตัวแปรที่ไม่ได้ประกาศ เนื่องจาก JavaScript ได้ยกระดับตัวแปรแล้ว จึงทราบว่าระบบจะสร้างตัวแปรภายในขอบเขตที่ระบุ อย่างไรก็ตาม แทนที่จะทำให้ตัวแปรนั้นพร้อมใช้งานก่อนการประกาศที่มีค่าเป็น undefined โปรแกรมล่ามจะแสดงข้อผิดพลาด ตัวแปรที่ประกาศด้วย let หรือ const (หรือ class) ถือว่าอยู่ใน "เขตตายตามเวลา" ("TDZ") ตั้งแต่จุดเริ่มต้นของบล็อกที่ล้อมรอบจนกว่าจะถึงจุดในโค้ดที่มีการประกาศตัวแปร

เขตเวลาที่ไม่มีสัญญาณทำให้ผู้เขียนเข้าใจลักษณะการทํางานของ let ได้ง่ายกว่า var และยังมีส่วนสําคัญต่อการออกแบบ const ด้วย เนื่องจากค่าคงที่เปลี่ยนแปลงไม่ได้ ค่าคงที่ที่ยกระดับไปยังด้านบนของขอบเขตและกำหนดค่าโดยนัยของ undefined จึงไม่สามารถเริ่มต้นด้วยค่าที่มีความหมายได้

ทดสอบความเข้าใจ

คุณใช้อักขระประเภทใดขึ้นต้นตัวระบุได้บ้าง

จดหมาย
ขีดล่าง
ตัวเลข

วิธีการใดที่แนะนำในการประกาศตัวแปรที่มีค่าเปลี่ยนแปลงได้ทุกเมื่อ

let
const
var