ตัวดำเนินการ II ในภาษา JavaScript

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

  • Compound assignment operators
  • Increment and decrement operators
  • Ternary operator
  • Nullish coalescing operator
  • การทดสอบค่าความจริง
  • การประเมินค่าแบบ Short-circuit

Compound assignment operators

ตัวดำเนินการกำหนดค่าแบบร่วม (Compound assignment operators) คือการใช้งานตัวดำเนินกำหนดค่า = ร่วมกับตัวดำเนินการประเภทอื่น ยกตัวอย่างเช่น ใช้ร่วมกับตัวดำเนินการทางคณิตศาสตร์ หรือตัวดำเนินการระดับบิต นี่จะทำให้เราสามารถใช้งานตัวดำเนินการในรูปแบบที่สั้นลงได้ นี่เป็นตัวอย่าง

let a = 10;
a += 5;         // Same as a = a + 5
console.log(a); // 15

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

a = a + 5

เนื่องจากว่าในกรณีนี้เราต้องการอัพเดทโดยใช้ค่าจากตัวแปรเดิม ดังนั้นเราสามารถใช้ตัวดำเนินการ += เพื่อลดการเขียน a ซ้ำสองครั้งในคำสั่งของโปรแกรมได้

และนี่เป็นตัวดำเนินการกำหนดค่าแบบร่วมทั้งหมดที่เราสามารถใช้ได้ในภาษา JavaScript

ตัวดำเนินการกำหนดค่าร่วมกับตัวดำเนินการทางคณิตศาตร์

ตัวดำเนินการ ตัวอย่าง มีค่าเท่ากับ
+= a += b a = a + b
-= a -= b a = a - b
*= a *= b a = a * b
/= a /= b a = a * b
%= a %= b a = a % b
**= a **= b a = a ** b

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

let score = 0;

score += 2;
console.log("You killed an enemy (+2)");
console.log("Current score: " + score);

score += 5;
console.log("You killed two enemies (+5)");
console.log("Current score: " + score);

score -= 3;
console.log("An enemy defeated you (-3)");
console.log("Current score: " + score);

score += 10;
console.log("You defeated the boss (+10)");

score *= 2;
console.log("Bonus: Your score was doubled (2x)");
console.log("Current score: " + score);

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

You killed an enemy (+2)
Current score: 2
You killed two enemies (+5)
Current score: 7
An enemy defeated you (-3)
Current score: 4
You defeated the boss (+10)
Bonus: Your score was doubled (2x)
Current score: 28

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

score += 2;
...
score += 5;
...
score -= 3;

เมื่อต้องการเพิ่มคะแนนเราจะใช้ตัวดำเนินการ += เนื่องจากคะแนนนั้นเพิ่มขึ้นจากค่าเดิมหรือคะแนนปัจจุบัน ส่วนการลดคะแนนนั้นจะใช้ตัวดำเนินการ -= และเช่นเดียวกัน คะแนนนั้นลดลงจากคะแนนปัจจุบัน

score *= 2;

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

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

let names = [
    "Andril",
    "Danny",
    "Georgie",
    "Mateo",
];

let count = 0;

for (let name of names) {
    count += name.length;
    console.log(`${name} (${name.length} chars) -> Counted ${count}`);
}

console.log(`Total ${count} chars`);

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

Andril (6 chars) -> Counted 6
Danny (5 chars) -> Counted 11
Georgie (7 chars) -> Counted 18
Mateo (5 chars) -> Counted 23
Total 23 chars

ในตัวอย่างนี้ เราได้ประกาศตัวแปรอาเรย์ names พร้อมกับใส่รายชื่อจำนวนหนึ่งไว้ในอาเรย์ และประกาศตัวแปร count สำหรับเก็บจำนวนตัวอักษรทั้งหมดที่จะนับ จากนั้นใช้คำสั่งวนซ้ำ for of เพื่อวนเอารายชื่อในอาเรย์มาหาความยาวทีละตัว

count += name.length;

ในบรรทัดนี้ เป็นการเรียกใช้งาน Property length เพื่อรับเอาความยาวของ String จากนั้นบวกค่าความยาวที่ได้มาเข้าไปในตัวแปร count ด้วยตัวดำเนินการ += ซึ่งการทำงานของมันจะเหมือนกับคำสั่งต่อไปนี้

count = count + name.length;

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

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

ตัวดำเนินการกำหนดค่าร่วมกับตัวดำเนินการระดับบิต

ตัวดำเนินการ ตัวอย่าง มีค่าเท่ากับ
&= a &= b a = a & b
|= a |= b a = a | b
^= a ^= b a = a ^ b
<<= a <<= b a = a << b
>>= a >>= b a = a >> b

นี่เป็นตัวอย่างการใช้งานตัวดำเนินการกำหนดค่าร่วมกับตัวดำเนินการระดับบิต

let a = 3;
a &= 5;         // equal to a = a & 5
console.log(a); // 1

ในตัวอย่างการทำงานของตัวดำเนินการคือทำการคำนวณหาผลลัพธ์ของ a & 3 และเก็บไว้ในตัวแปร a เช่นเดิม

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

let a = 1;
let year = 2004;
for (let i = 0; i < 10; i++) {
    console.log(year + ": " + a + " GB");
    a <<= 1;    //  a = a << 1;
    year += 2;
}

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

2004: 1 GB
2006: 2 GB
2008: 4 GB
2010: 8 GB
2012: 16 GB
2014: 32 GB
2016: 64 GB
2018: 128 GB
2020: 256 GB
2022: 512 GB

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

คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับกฏของมัวร์ได้ที่ กฎของมัวร์ (Wikipedia)

Increment and decrement operators

ตัวดำเนินการเพิ่มค่า (Increment operator) นั้นใช้สำหรับเพิ่มค่าในตัวแปรขึ้นทีละ 1 ในขณะที่ตัวดำเนินการลดค่า (Decrement operator) นั้นใช้สำหรับลดค่าในตัวแปรลงทีละ 1 ตัวดำเนินการเหล่านี้มีประโยชน์และช่วยอำนวยความสะดวกเมื่อเราต้องการเพิ่มหรือลดค่าตัวแปรในรูปแบบดังกล่าว ยกตัวอย่างเช่น

let i = 1;
i++;    // i = i + 1
console.log(i); // 2

let j = 10;
j--;    // j = j -1
console.log(j); // 9

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

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

let lang = ["Python", "JavaScript", "TypeScript", "Ruby", "Go"];
for (let i = 0; i < lang.length; i++) {
    console.log("lang[" + i +"]: " + lang[i]);
}

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

lang[0]: Python
lang[1]: JavaScript
lang[2]: TypeScript
lang[3]: Ruby
lang[4]: Go

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

การทำงานแบบ Prefix และ Postfix

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

ชื่อตัวดำเนินการ ตัวอย่าง การทำงาน
Prefix increment ++variable บวกค่าก่อนส่งกลับ
Prefix decrement --variable ลบค่าก่อนส่งกลับ
Postfix increment variable++ บวกค่าหลังจากส่งกลับ
Postfix decrement variable-- ลบค่าหลังจากส่งกลับ

การใช้งานตัวดำเนินการ Increment และ Decrement ในรูปแบบทั้งหมดนั้นจะส่งค่ากลับมาด้วย ตัวดำเนินการแบบ Prefix จะเพิ่มหรือลดค่าในตัวแปรก่อนค่อยส่งค่ากลับ ส่วนตัวดำเนินการแบบ Postfix จะส่งค่าเดิมในตัวแปรกลับมาก่อนแล้วค่อยเพิ่มหรือลดค่า นี่เป็นตัวอย่าง

prefix_postfix.js
let a = 10;
let b = ++a;    // 11

let c = 10;
let d = c++;    // 10

ในตัวอย่าง เป็นการแสดงความแตกต่างของการทำงานระหว่างตัวดำเนินการแบบ Prefix และ Postfix เราได้ประกาศตัวแปร a และ c และกำหนดค่าเริ่มต้นให้กับตัวแปรทั้งสองเท่ากันคือ 10

let b = ++a;

เราเรียกใช้งานตัวดำเนินการเพิ่มค่าในตัวแปร a ในรูปแบบ Prefix ++a ตัวดำเนินการได้เพิ่มค่าในตัวแปรขึ้น 1 และส่งค่ากลับมาเป็นค่าที่เพิ่มไปแล้ว นั่นทำให้ค่าในตัวแปร b เท่ากับ 11

let d = c++;

จากนั้นเป็นการใช้งานตัวดำเนินการเพิ่มค่าแบบ Postfix c++ ตัวดำเนินการจะส่งค่าปัจจุบันในตัวแปรกลับมาก่อน จากนั้นค่อยเพิ่มค่าในตัวแปร c ขึ้นไป 1 นั่นทำให้ค่าในตัวแปร d มีค่าเท่ากับเดิมนั่นเอง

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

let i = 1;
i++; // or ++i;
console.log(i);  // 2

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

incrementing_id.js
let names = [
    "Andril",
    "Danny",
    "Georgie",
    "Mateo"
];

let id = 0;
for (let name of names) {
    console.log(++id, name);
}

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

1 Andril
2 Danny
3 Georgie
4 Mateo
5 Metin

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

Ternary operator

ตัวดำเนินการ Ternary (หรือ Ternary condition) เป็นตัวดำเนินการที่ทำงานกับตัวถูกดำเนินการสามตัว ตัวดำเนินการนี้เป็นที่รู้จักกันในชื่อว่าคำสั่ง if-else รูปแบบสั้น เนื่องจากมันใช้สำหรับเลือกค่าจากเงื่อนไขที่เราสร้างขึ้น นี่เป็นรูปแบบการใช้งาน

let returnedValue = condition ? value1 : value2;

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

let loggedIn = 1;
let message = loggedIn == 1 ? "Logged in" : "Not logged in";
console.log("You're " + message);

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

You're Logged in

ในตัวอย่าง เรามีตัวแปร loggedIn ที่เก็บค่าเป็นสถานะว่าผู้ใช้งานเข้าสู่ระบบอยู่หรือไม่ โดยเก็บค่าเป็น 1 ซึ่งหมายถึงกำลังอยู่ในระบบ และ 0 หากไม่ได้กำลังอยู่ในระบบ

let message = loggedIn == 1 ? "Logged in" : "Not logged in";

จากนั้นเราใช้ตัวดำเนินการ Ternary เพื่อสร้างเงื่อนไข loggedIn == 1 ที่ส่งค่ากลับเป็นข้อความที่บอกว่าเข้าสู่ระบบอยู่หรือไม่ เนื่องจากเงื่อนไขเป็นจริง นั่นทำให้ค่าที่ได้รับกลับมาในตัวแปร message เป็น "Logged in"

จากในตัวอย่างสำหรับการใช้งานตัวดำเนินการ Ternary นั้น เราสามารถเขียนได้โดยการใช้งานคำสั่ง if ยกตัวอย่างเช่น

let loggedIn = 1;

if (loggedIn == 1) {
    console.log("You're Logged in");
} else {
    console.log("You're Not logged in");
}

ในตัวอย่างนี้เป็นการใช้งานคำสั่ง if สำหรับตรวจสอบเงื่อนไขแทนตัวดำเนินการ Ternary operator ซึ่งสามารถทำได้เช่นเดียวกันและมันได้ผลลัพธ์ที่เหมือนกัน แต่เราต้องเขียนยาวกว่า และต้องเรียกใช้งานฟังก์ชัน console.log หลายครั้ง

สำหรับการใช้งานตัวดำเนินการ Ternary operator นั้น ทุกๆ Expression สามารถใช้งานเป็นค่าส่งกลับของตัวดำเนินการได้ไม่ว่าจะเป็น Literal ตัวแปร หรือการเรียกใช้ฟังก์ชัน ยกตัวอย่างเช่น

function add(a, b) {
    return a + b;
}

function subtract(a, b) {
    return a - b;
}

let a = 5;
let b = 3;
let op = "+";

let result = op == "+" ? add(a, b) : subtract(a, b);
console.log(`${a} ${op} ${b} = ${result}`);

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

5 + 3 = 8

ในตัวอย่าง เป็นการเรียกใช้งานฟังก์ชันโดยขึ้นอยู่กับค่าในตัวแปร op ถ้าหากค่าในตัวแปรเป็น + ฟังก์ชัน add จะถูกเรียกใช้งาน ไม่เช่นนั้นจะเป็นฟังก์ชัน subtract ที่ถูกเรียกแทน ซึ่งนี่น่าจะช่วยให้คุณเข้าใจวิธีการนำมันไปใช้งานในรูปแบบต่างๆ ได้มากขึ้น

Nullish coalescing operator

ตัวดำเนินการ Nullish coalescing เป็นตัวดำเนินการที่ใช้เพื่อเลือกค่าระหว่างสองค่าหรือใช้สำหรับกำหนดค่าเริ่มต้นให้กับตัวแปร ในกรณีที่ค่านั้นเป็น null หรือ undefined นี่เป็นรูปแบบการใช้งาน

let returnedValue = value1 ?? value2;

ในการใช้งานตัวดำเนินการ Nullish coalescing (??) เพื่อเลือกค่าระหว่างสองค่าที่อยู่ทางด้านซ้ายและขวาของตัวดำเนินการ ถ้าหาก value1 มีค่าเป็น null หรือ undefined ผลลัพธ์ที่ได้จะเป็นค่าจากทางด้านขวา value2 แต่ถ้าหากไม่ใช่ผลลัพธ์ทีไ่ด้จะเป็นค่าจากตัวแปร value1

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

let name = null;
console.log(name ?? "Guest");   // Guest

name = "Metin";
console.log(name ?? "Guest");   // Metin

ในตัวอย่าง เนื่องจากค่าในตัวแปร name นั้นเป็น null ดังนั้นผลลัพธ์ที่ได้จึงเป็น "Guest" และในคำสั่งต่อมาผลลัพธ์จะได้เป็น "Metin" ซึ่งเป็นค่าของตัวแปร name นั่นเอง

และนี่เป็นอีกตัวอย่างหนึ่งสำหรับการใช้งานตัวดำเนินการ Nullish coalescing เพื่อกำหนดค่าเริ่มต้นให้กับตัวแปร

let user1 = {
    name: "Metin",
    locale: "th"
};

let user2 = {
    name: "Mateo"
};

let user1Locale = user1.locale ?? "en";
let user2Locale = user2.locale ?? "en";

console.log("user1Locale: " + user1Locale);
console.log("user2Locale: " + user2Locale);

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

user1Locale: th
user2Locale: en

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

let user1Locale = user1.locale ?? "en";
let user2Locale = user2.locale ?? "en";

เนื่องจาก user1.locale นั้นมีค่าเป็น "th" ดังนั้นค่าในตัวแปร user1Locale จะเป็นค่าดังกล่าว ส่วน user2.locale นั้นไม่มี Property อยู่หรือมีค่าเป็น undefined ดังนั้นค่าในตัวแปร user2Locale จะเป็นค่าเริ่มต้น "en" แทน

หมายเหตุ: ตัวดำเนินการ Nullish coalescing นั้นเป็นตัวดำเนินการที่เพิ่มเข้ามาภาษา JavaScript ไม่นานมานี้ใน (ES11) ECMAScript 2020 ดังนั้นในการใช้งานมันคุณใช้ Node.js เวอร์ชัน 14 หรือใหม่กว่า

การทดสอบค่าความจริง

การทดสอบค่าความจริง (Truth Value Testing) คือการตรวจสอบว่าข้อมูลประเภทต่างๆ นั้นสามารถประเมินเป็นค่า Boolean จริงหรือเท็จได้ นั่นหมายความว่าเราสามารถใช้มันในบริษทของ Boolean ยกตัวอย่างเช่น 1 นั้นถูกประเมินค่าเป็น true และ 0 นั้นถูกประเมินค่าเป็น false

นี่เป็นตารางที่อธิบายว่าข้อมูลแต่ละประเภทในภาษา JavaScript ถูกประเมินค่าเป็นของ Boolean อย่างไร

ประเภทข้อมูล มีค่าเทียบเท่า true มีค่าเทียบเท่า false
ตัวเลข ค่าอื่นๆ เช่น 1, -1, 0.5 0
String ค่าอื่นๆ "hello", "0" ค่าว่าง ""
Boolean true false
BigInt ค่าอื่นๆ เช่น -1n, 1n, 5n 0n
Symbol ทุกค่า เช่น Symbol(), Symbol("name") -
Undefined - มีค่าเดียวคือ undefined
Null - มีค่าเดียวคือ null
Array มีค่าเป็นจริงเสมอ -
Object มีค่าเป็นจริงเสมอ -
Function มีค่าเป็นจริงเสมอ -

จะเห็นว่าในตารางนั้นตัวเลขทุกตัวมีค่าเทียบเท่ากับ true ยกเว้น 0 ที่มีค่าเทียบเท่ากับ false เช่นเดียวกับค่าของ String ซึ่งทุกค่าของ String นั้นมีค่าเทีียบเท่ากับ true ยกเว้น String ว่างหรือที่มีความเป็นศูนย์เท่านั้นที่เทียบเท่ากับ false นั่นหมายความว่าเราสามารถใช้ข้อมูลประเภทใดๆ ในการทำงานกับคำสั่งเงื่อนไขหรือตัวดำเนินการที่ทำงานกับค่าของ Boolean ได้

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

let n = 1;

if (n) {
    console.log("n is " + n);
} else {
    console.log("n is zero");
}
// Output: n is 1

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

และเช่นเดียวกันกับคำสั่ง for หรือ while loop นี่เป็นตัวอย่างในการใช้งานคำสั่ง while loop เพื่อแสดงตัวเลขจาก 5 - 1 และลูปจบการทำงานเมื่อค่าในตัวแปรเท่ากับ 0

let n = 5;
while (n) {
    console.log(n);
    n--;
}

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

5
4
3
2
1

ในขณะที่ตัวเลขในตัวแปร n นั้นมากกว่า 0 มันถูกประเมินค่าเป็นจริงนั่นทำให้การแสดงผลใน loop ทำงาน จนกระทั่งค่าในตัวแปรลดลงเหลือเท่ากับ 0 ซึ่งถูกประเมินค่าเป็นเท็จ และลูปจบการทำงาน

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

let name = "Metin";
if (name) {
    console.log("Name has a value");
} else {
    console.log("Name is empty");
}
// Output: Name has a value

ในตัวอย่าง เป็นการตรวจสอบค่าในตัวแปร name นั้นมีค่าหรือไม่ ซึ่งในความเป็นจริงแล้วเราสามารถสร้างเงื่อนไขได้จาก name != "" แต่นั่นมันยาวเกินไปสำหรับเราในตอนนี้

นอกจากนี้ เราสามารถใช้ตัวดำเนินการ Not เพื่อกลับค่าของ Boolean ได้ ยกตัวอย่างเช่น ถ้าหากเราสนใจเพียงแค่ว่าค่าในตัวแปรนั้นเป็น String ว่างหรือไม่ เราสามารถเขียนเช่นนี้ได้

let name = "";
if (!name) {
    console.log("Oops! Please enter your name.");
}
// Output: Oops! Please enter your name.

ในตัวอย่างนั้นมีการทำงานคือ ตอนแรกค่าในตัวแปร name นั้นถูกแปลงเป็น Boolean ซึ่งมีค่าเท่ากับ false หลังจากนั้นตัวดำเนินการ Not กลับค่ามันให้เป็น true และทำให้โค้ดในบล็อคของคำสั่ง if ทำงาน

อีกตัวอย่างหนึ่งในการตรวจสอบค่า เราสามารถใช้คำสั่ง if เพื่อตรวจสอบค่าทั้งหมดที่มีค่าเทียบเท่ากับ false ได้ นี่เป็นตัวอย่าง

let answer = null;
if (!answer) { // (1)
    console.log("The value is null or zero or empty string ");
}
if (answer === null) {  // (2)
    console.log("The value is null.");
}

ในการตรวจสอบเงื่อนไข (1) เป็นการตวจสอบค่าทั้งหมดที่มีค่าเทียบเท่ากับ false เช่นเมื่อค่าในตัวแปร answer เป็น null, undefined, หรือ 0 เป็นต้น อย่างไรก็ตาม ในกรณีที่คุณต้องการตรวจสอบเพียงแค่ค่าๆ เดียว เช่น null คุณจะต้องใช้ตัวดำเนินการเปรียบเทียบเหมือนที่เงื่อนไข (2) แทน

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

การประเมินค่าแบบ Short-circuit

โดยทั่วไปแล้วตัวดำเนินตรรกศาสตร์ And (&&) และ OR (||) มักจะใช้กับค่าของ Boolean อย่างไรก็ตาม มันสามารถทำงานได้กับข้อมูลทุกประเภท ดังนั้นในบทนี้เราจะพูดถึงการใช้งานตัวดำเนินการทั้งสองในรูปแบบ Short-circuit สำหรับเลือกค่าของข้อมูล

Short-circuit OR

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

let result = value1 || value2;
let result = value1 || value2 || ... || valueN;

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

let user = {
    name: "",
    username: "metin03",
    email: "metin@gmail.com"
};

let displayName = user.name || user.username || user.email;
console.log(displayName);   // metin03

ในตัวอย่าง เรามีออบเจ็คของ user ที่เก็บค่าชืื่อ ชื่อผู้ใช้ และอีเมล และเราต้องการที่จะแสดงชื่อของผู้ใช้คนนี้ อย่างไรก็ตาม ค่าทั้งหมดนั้นสามารถมีหรือไม่มีก็ได้ ดังนั้นเราจึงใช้ตัวดำเนินการ OR เพื่อเลือกเอาค่าแรกที่พบก่อน โดยให้ความสำคัญจาก name, username และตามด้วย email ตามลำดับ

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

let user = {
    name: "",
    username: ""
};

let displayName = user.name || user.username || "Default";
console.log(displayName);   // Default

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

Short-circuit AND

ตัวดำเนินการ And จะส่งค่ากลับเป็นค่าแรกที่มีค่าเทียบเท่ากับ false ไม่เช่นนั้นค่าสุดท้ายจะถูกส่งกลับแทน นี่เป็นรูปแบบการใช้งาน

let result = value1 && value2;
let result = value1 && value2 && ... && valueN;

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

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

let message = "Hi";
let name = "Metin";
message && name && console.log(message + " " + name);

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

Hi Metin

คำสั่งจะทำงานไปเรื่อยๆ จะกว่าจะพบกับค่า false เนื่องจากในตัวแปรทั้งสองนั้นมีค่า ดังนั้นโปรแกรมทำงานต่อไปยังคำสั่ง console.log และแสดงค่าของตัวแปรทั้งสองออกทางหน้าจอ และจากในตัวอย่างนี้ เราสามารถเขียนโดยใช้คำสั่ง if ซึ่งจะได้ผลลัพธ์เช่นเดียวกัน

let message = "Hi";
let name = "Metin";
if (message && name) {
    console.log(message + " " + name);
}

อีกตัวอย่างสำหรับการใช้งานตัวดำเนินการ AND ที่พบเห็นได้บ่อยคือใช้สำหรับอ่านค่า Proerty ที่ซ้อนกันของออบเจ็ค ยกตัวอย่างเช่น

let user = {
    name: "Metin",
    location: {
        name: "Bangkok",
        coordinate: { lat: 100, lng: 200 }
    }
};

let latitude = user.location && user.location.coordinate && 
user.location.coordinate.lat;
if (latitude) {
    console.log("Got your latitude: " + latitude);
} else {
    console.log("No latitude available.");
}

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

Got your latitude: 100

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

let latitude = user.location && user.location.coordinate && 
user.location.coordinate.lat;

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

หลังจากนั้นให้คุณลองลบ coordinate ออกไปจากออบเจ็คแบบนี้

let user = {
    name: "Metin",
    location: {
        name: "Bangkok"
    }
};

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

No latitude available.

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

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