ตัวแปร ในภาษา TypeScript

17 December 2021

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

  • ตัวแปรคืออะไร
  • การประกาศตัวแปร
  • โปรแกรมคำนวณดอกเบี่้ยเงินฝาก
  • ขอบเขตของตัวแปร

ตัวแปรคืออะไร

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

ในภาษา TypeScript เราสามารถใช้ตัวแปรเพื่อเก็บข้อมูลได้ทุกประเภท ไม่ว่าจะเป็น ตัวเลข Boolean String ออบเจ็ค คลาส ฟังก์ชัน หรือข้อมูลประเภทอื่นๆ นี่เป็นรูปแบบของการประกาศตัวแปรในภาษา TypeScript

let name: type = value;

การประกาศตัวแปรจะใช้คำสั่ง let ตามด้วยชื่อของตัวแปร name นี่จะใช้สำหรับอ้างถึงค่าในตัวแปรสำหรับกำหนดและอ่านค่าจากหน่วยความจำ จากนั้นตามด้วยประเภทข้อมูล type และกำหนดค่าเริ่มต้นให้กับตัวแปรถ้าหากมี

การตั้งชื่อให้ตัวแปรจะต้องประกอบไปด้วยตัวอักษร (a-z, A-Z) ตัวเลข (0-9) และเครื่องหมาย Underscore (_) ชื่อของตัวแปรไม่สามารถเริ่มต้นด้วยตัวเลขได้ แม้คุณจะสามารถใช้ตัวอักษรและเครื่องหมายอื่นในการตั้งชื่อตัวแปรได้ แต่นั่นเป็นสิ่งที่ไม่แนะนำ

let name: type;
let name = value;

นอกจากนี้ คุณยังสามารถประกาศตัวแปรโดยละเว้นค่าเริ่มต้นได้ ในกรณีนี้ตัวแปรจะมีค่าเป็น undefined และสามารถละเว้นประเภทข้อมูลได้ โดย TypeScript จะคาดเดาประเภทข้อมูลจาก value ให้อัตโนมัติหรือเรียกว่า Type inferring

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

การใช้งานตัวแปรเป็นเรื่องพื้นฐานในการเขียนโปรแกรม เราสามารถใช้มันเพื่อเก็บข้อมูล นำไปคำนวณ และอ่านค่าเพื่อนำมาใช้งานในโปรแกรมได้ นี่เป็นตัวอย่างของการประกาศและใช้งานตัวแปรสำหรับเก็บชื่อและอายุในภาษา TypeScript

let name: string = "John";
let age: number = 30;
console.log(`${name} is ${age} years old`);

นี่เป็นผลลัพธ์การทำงานของโปรแกรม

John is 30 years old

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

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

let score: number;
score = 90;

ในตัวอย่างนี้ เราประกาศตัวแปร score สำหรับเก็บค่าที่มีประเภทข้อมูลเป็น number ซึ่งในตอนแรกมันจะมีค่าเป็น undefined จากนั้นกำหนดค่าให้กับตัวแปรในภายหลังในบรรทัดถัดมาเป็น 90

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

let year: number = 2021;
console.log("This year " + year);
number = 2022;
console.log("Next year " + year);

นี่เป็นผลลัพธ์การทำงานของโปรแกรม

This year 2021
Next year 2022

ในตัวอย่างนี้ เราได้ประกาศตัวแปรประเภทตัวเลขสำหรับเก็บปี 2021 จากนั้นเปลี่ยนค่าในตัวแปรเป็นปี 2022 หลังจากที่ใช้งานค่าก่อนหน้าไปแล้ว

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

let favoriteFood: string = "Pad Thai";
let commentCount: number = 10;
let dateOfBirth = new Date("2021-07-03");

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

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

let favorite_food: string = "Pad Thai";
let comment_count: number = 10;
let date_of_birth = new Date("2021-07-03");

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

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

let 2you: string; // Error
let my.name: string; // Error

นี่เป็นการประกาศตัวแปรที่ไม่ถูกต้อง เนื่องจากตัวแปรแรกขึ้นต้นด้วยตัวเลข 2 และตัวแปรที่สองมีเครื่องหมายจุด (.) ซึ่งเป็นเครื่องหมายที่ไม่อนุญาติ โดยปกติแล้วเครื่องหมายที่มักใช้ในชื่อตัวแปรจะเป็น Underscore แม้เครื่องหมายอื่นอาจสามารถใช้งานได้ แต่ไม่แนะนำ

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

function greet(name: string) {
    console.log(`Hi ${name}`);
}

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

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

type User = {
    id: number,
    name: string
};

let user: User = {
    id: 1,
    name: "Metin"
};

class Dog {
    name: string;
    color: string;
}

let myDog = new Dog();
myDog.name = "Bruce";
myDog.color = "Brown";

console.log(user);
console.log(myDog);

นี่เป็นผลลัพธ์การทำงานของโปรแกรม

{ id: 1, name: 'Metin' }
Dog { name: 'Bruce', color: 'Brown' }

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

โปรแกรมคำนวณดอกเบี่้ยเงินฝาก

หลังจากได้เห็นตัวอย่างการทำงานพื้นฐานของตัวแปรไปแล้ว ต่อไปจะเป็นการเขียนโปรแกรมเพื่อประยุกต์ใช้งานตัวแปรในภาษา TypeScript

นี่เป็นโปรแกรมคำนวณดอกเบี่้ยเงินฝากแบบทบต้นจากธนาคาร ยกตัวอย่างเช่น ถ้าคุณมีเงิน 150,000 บาท และนำไปฝากธนาคารในอัตราดอกเบี้ย 2.5% ต่อปี เป็นระยะเวลา 10 ปี มาดูกันว่าจะได้รับดอกเบี้ยเท่าไรในตอนท้าย เราสามารถเขียนโปรแกรมเพื่อหาคำตอบได้

interest_calculator.ts
let money: number = 150000;
let interestRate: number = 2.5;
let year: number = 10;

let totalInterest: number = 0;
let principle: number = money;

console.log("# | Priciple | Interest | New balance");

for (let i: number = 1; i <= year; i++) {
    let interest: number = principle * interestRate / 100;
    let newBalance: number = principle + interest;

    console.log(
        `${i} | ` +
        `${principle.toFixed(2)} | ` +
        `${interest.toFixed(2)} | ` +
        `${newBalance.toFixed(2)}`
    );

    totalInterest += interest;
    principle = newBalance;
}

console.log(`Base money: ${money.toFixed(2)}`);
console.log(`Total interest: ${totalInterest.toFixed(2)}`);
console.log(`Total money: ${principle.toFixed(2)}`);

นึี่เป็นผลลัพธ์การทำงานของโปรแกรม

# | Principle | Interest | New balance
1 | 150000.00 | 3750.00 | 153750.00
2 | 153750.00 | 3843.75 | 157593.75
3 | 157593.75 | 3939.84 | 161533.59
4 | 161533.59 | 4038.34 | 165571.93
5 | 165571.93 | 4139.30 | 169711.23
6 | 169711.23 | 4242.78 | 173954.01
7 | 173954.01 | 4348.85 | 178302.86
8 | 178302.86 | 4457.57 | 182760.43
9 | 182760.43 | 4569.01 | 187329.45
10 | 187329.45 | 4683.24 | 192012.68
Base money: 150000.00
Total interest: 42012.68
Total money: 192012.68

เพื่อเล่นสนุกกับโปรแกรม คุณสามารถลองเปลี่ยนค่าของเงินต้นในตัวแปร money อัตราดอกเบี้ยต่อปีในตัวแปร interestRate และระยะเวลาที่ต้องการฝากในตัวแปร year และดูว่าจำนวนเงินที่ได้รับในตอนท้ายจะเป็นอย่างไร

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

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

ขอบเขตของตัวแปร (Variable scope) คือสถานที่หรือบล็อคที่ตัวแปรถูกประกาศและส่งผลให้ตัวแปรมีขอบเขตในที่ดังกล่าว โดยปกติแล้วขอบเขตของตัวแปรในภาษา TypeScript สามารถแบ่งออกเป็น 3 ระดับ ได้แก่ Global, Module และ Local

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

program.ts
let siteName: string = "MarcusCode";
let siteColor: string = "Blue";

ในตัวอย่างนี้ ทั้งสองตัวแปรม่ีขอบเขตเป็นแบบ Global เนื่องจากมันถูกประกาศใน Top level ของโปรแกรม ดังนั้นสำหรับโค้ดทั้งหมดที่เขียนภายในไฟล์เดียวกันคือ program.ts จะสามารถเข้าถึงและใช้งานตัวแปรเหล่านี้ได้

ในกรณีนี้ไฟล์โปรแกรม program.ts จะถือว่าเป็นโมดูลด้วยเช่นเดียวกัน ใน Node.js ถ้าคุณสร้างไฟล์ใหม่ขึ้นมาถือว่าคุณสร้างโมดูลโดยปริยาย และตัวแปรที่ประกาศในโมดูลจะสามารถใช้ได้ในโมดูลที่มันประกาศเท่านั้น ในตัวอย่างนี้ เป็นโปรแกรมที่มีสองโมดูลซึ่งประกอบไปด้วย site.ts และ main.ts

site.ts
export let name: string = "MarcusCode";
export let color: string = "Blue";
export let year: number = 2014;
main.ts
import * as site from "./site";

console.log("Site info");
console.log("Name:", site.name);
console.log("Color:", site.color);
console.log("Launched:", site.year);

let name = "Metin";
let hobby = "Reading";

console.log("Author info");
console.log("Name:", name);
console.log("Hobby:", hobby);

นี่เป็นผลลัพธ์การทำงานของโปรแกรม

Site info
Name: MarcusCode
Color: Blue
Launched: 2014
Author info
Name: Metin
Hobby: Reading

โปรแกรมนี้ประกอบไปด้วยสองโมดูล โมดูลหลักคือ main.ts ที่ได้มีการนำเข้าค่าจากโมดูล site.ts จะเห็นว่าแต่ละโมดูลสามารถมีตัวแปรโดยที่ไม่ขัดแย้งกัน ในกรณีนี้คือตัวแปร name ที่ประกาศในแต่ละโมดูล นั่นหมายความว่าแต่ละโมดูลมีขอบเขตตัวแปรเป็นของมันเอง และสามารถส่งค่าออกไปใช้งานนอกโมดูลได้

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

function countVowels(text: string): number {
    let count: number = 0;
    for (let ch of text) {
        if (["a", "e", "i", "o", "u"].indexOf(ch) !== -1) {
            count++;
        }
    }
    return count;
}

let siteCount: number = countVowels("marcuscode");
let count: number = countVowels("How many vowels in this string?");

console.log(`Vowels in site name: ${siteCount}`);
console.log(`How many vowels in this string?: ${count}`);

นี่เป็นผลลัพธ์การทำงานของโปรแกรม

Vowels in site name: 4
How many vowels in this string?: 7

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

let count: number = countVowels("How many vowels in this string?");

จะเห็นว่าในส่วน Top level ของโปรแกรม เราได้ประกาศตัวแปรชื่อเดียวกันกับในฟังก์ชัน count นี่จะถือว่าเป็นคนละตัวแปรกันเนื่องจากมันถูกประกาศคนละขอบเขต และแต่ขอบเขตสามารถใช้งานตัวแปรได้อย่างไม่มีข้อขัดแย้ง

กฏนี้นำไปใช้เช่นเดียวกันกับบล็อคที่เกิดจากการใช้คำสั่งควบคุมอย่าง if else for while หรือ do while นี่เป็นตัวอย่างของโปรแกรมสำหรับบวกหรือลบตัวเลข

let a: number = 2;
let b: number = 3;
let answer: number;

let op: string = "add";

if (op == "add") {
    console.log("adding numbers");
    let c: number = a + b;
    answer = c;
} else {
    console.log("subtracting numbers");
    let c: number = a - b;
    answer = c;
}

console.log(`answer = ${answer}`);

นี่เป็นผลลัพธ์การทำงานของโปรแกรม

adding numbers
answer = 5

ในตัวอย่างนี้ เราได้ใช้คำสั่ง if else สำหรับตรวจสอบเงื่อนไขในตัวแปร op ว่าต้องการทำอะไรกับค่าในตัวแปร a และ b ในบล็อคของคำสั่ง if ได้ประกาศตัวแปร c สำหรับเก็บผลลัพธ์ที่ได้จากการคำนวณ ดังนั้นตัวแปร c จะสามารถใช้ได้ภายในบล็อคนี้เท่านั้น

และในคำสั่ง else ก็ได้ประกาศตัวแปร c เช่นเดียวกัน นี่เป็นตัวแปรคนละตัวกับบล็อคของคำสั่ง if เนื่องจากนี่เป็นคนละบล็อคกัน ซึ่งตัวแปร c ที่ประกาศในบล็อคทั้งสองจะถูกทำลายเมื่อจบการทำงานของบล็อค

let c: number = a + b;
answer = c;

เนื่องจากทั้งสองบล็อคนี้ถูกประกาศใน Top level นั่นทำให้มันสามารถเข้าถึงตัวแปร a, b และ answer ที่ประกาศใน Top level ได้

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

console.log(`answer = ${c}`);

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

let message = "End of greeting program";
let names: string[] = ["Chris", "Julia", "Brian", "Lily"];

names.forEach((name, index) => {
    let word = index % 2 == 0 ? "Hello" : "Hi";
    let message = `${word} ${name}`;
    console.log(message);
});

console.log(message);

นี่เป็นผลลัพธ์การทำงานของโปรแกรม

Hello Chris
Hi Julia
Hello Brian
Hi Lily
End of greeting program

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

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

let message = `${word} ${name}`;
console.log(message);

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

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

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

บทความนี้เป็นประโยชน์หรือไม่?Yes·No