0Pricing
JavaScript Academy · บทเรียน

สแต็กการเรียก

ดูว่าการเรียกฟังก์ชันถูกติดตามไว้อย่างไร

สแต็กการเรียก เป็นบทเรียน JavaScript Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน JavaScript Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส JavaScript Academy มีบทเรียนทั้งหมด 4 บทเรียน

สแตกการเรียกใช้คืออะไร

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

โครงสร้างนี้เป็นแบบ LIFO: เข้าหลัง ออกก่อน

การใส่และนำออกจากสแตก

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

function first() {
  console.log('first start');
  second();
  console.log('first end');
}

function second() {
  console.log('second');
}

first();

LIFO ในการทำงานจริง

ฟังก์ชันที่ถูกเรียกใช้ล่าสุดต้องทำงานให้เสร็จก่อนฟังก์ชันที่อยู่ด้านล่างจึงจะทำงานต่อได้ การเรียกใช้ด้านในจะเสร็จก่อน แม้จะเริ่มต้นทีหลังก็ตาม

function a() {
  console.log('enter a');
  b();
  console.log('exit a');
}
function b() {
  console.log('enter b');
  c();
  console.log('exit b');
}
function c() {
  console.log('c runs');
}
a();

การทำงานตามลำดับหมายถึงการหยุดรอ

JavaScript ทำงาน ทีละอย่าง บนเธรดเดียว ขณะที่สแตกมีเฟรมอยู่ จะไม่มีสิ่งอื่นทำงาน โค้ดแบบทำงานตามลำดับจะ ขัดขวางการทำงานจนกว่าจะเสร็จ

console.log('start');

function busy() {
  let sum = 0;
  for (let i = 0; i < 1000; i++) sum += i;
  return sum;
}

console.log(busy());
console.log('end');

ค่าที่ส่งกลับไหลลงด้านล่าง

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

function square(n) {
  return n * n;
}
function sumOfSquares(a, b) {
  return square(a) + square(b);
}

console.log(sumOfSquares(3, 4));

การเรียกซ้ำทำให้สแตกเติบโต

การเรียกซ้ำแต่ละครั้งจะเพิ่มเฟรมอีกหนึ่งเฟรม สแตกจะขยายตัวจนกว่าจะพบกรณีฐาน จากนั้นจึงคลายกลับทีละเฟรม

function countdown(n) {
  if (n === 0) {
    console.log('liftoff');
    return;
  }
  console.log(n);
  countdown(n - 1);
}

countdown(3);

สแตกเต็ม

สแตกมีขนาดจำกัด การเรียกซ้ำที่ไม่มีกรณีฐานจะเพิ่มเฟรมต่อไปจนกระทั่งเอนจินโยน RangeError: ขนาดสแตกการเรียกใช้สูงสุดเกินขีดจำกัด

function endless(n) {
  return endless(n + 1);
}

try {
  endless(1);
} catch (e) {
  console.log(e.name);
}

ลำดับการทำงานคาดเดาได้

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

function outer() {
  console.log(1);
  inner();
  console.log(3);
}
function inner() {
  console.log(2);
}
outer();
console.log(4);

จุดที่การทำงานแบบไม่พร้อมกันเข้ามา

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

นี่คือสะพานไปสู่วงจรเหตุการณ์

console.log('A');
setTimeout(() => console.log('B (later)'), 0);
console.log('C');

สแตกต้องว่างก่อน

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

console.log('sync 1');
setTimeout(() => console.log('timeout'), 0);
console.log('sync 2');
console.log('sync 3');

เหตุใดสแตกการเรียกใช้จึงสำคัญ

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

function compute() {
  return [1, 2, 3].reduce((a, b) => a + b, 0);
}
console.log('before');
console.log(compute());
console.log('after');

ตรวจสอบความเข้าใจอย่างรวดเร็ว

สแตกการเรียกใช้ทำตามหลักการจัดลำดับแบบใด

ทบทวน: สแตกการเรียกใช้

คุณได้เรียนรู้แกนหลักของการทำงานของเอนจิน ดังนี้

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

คำถามที่พบบ่อย

บทเรียน “สแต็กการเรียก” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “สแต็กการเรียก” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส JavaScript Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส JavaScript Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “สแต็กการเรียก”

ดูว่าการเรียกฟังก์ชันถูกติดตามไว้อย่างไร คุณปฏิบัติ JavaScript Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน JavaScript Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน JavaScript Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “สแต็กการเรียก” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน JavaScript Academy นี้ได้ไหม

ได้ บทเรียน JavaScript Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. สแต็กการเรียก
  2. งานแมโครและคิวงาน
  3. งานไมโครและพรอมิส
  4. queueMicrotask และลำดับการทำงาน
← กลับไปที่ JavaScript Academy