Hoisting ใน Javascript คืออะไร

13 February, 2019, By Tar Jarupong

สำหรับใครที่เคยชินกับ var มาแล้วคงเข้าใจอยู่แล้วว่ามี let & const ที่มาแทนที่รุ่นพี่ไปแล้วเพราะว่า 2 ตัวนี้แก้ปัญหาหาเรื่อง hoisting แต่ๆ ส่วนใหญ่แล้วเราเคยได้ยินอย่างว่า

อย่าไปใช้ var นะเพราะมันให้เกิด hoisting

แล้วอะไรคือ hoisting กันล่ะวันนี้ผมจะมาอธิบายให้ฟังกันครับ เริ่ม~~~


Hoisting ?

       hoisting คือการประกาศตัวแปรแต่ยังไม่มีการกำหนดค่าเข้าไป และอุ้มตัวแปรไปอยู่บนสุดครับ


console.log(a);
    var a = 'สวัสดีครับ';

ถ้าเป็นภาษาอื่นมันคง error ว่าไม่ได้มีการประกาศตัวแปร a โว้ยไปประกาศส่ะ แต่!ใน JS อะไรก็เกิดขึ้นได้ถ้ามีปาปิก้า มันจะขึ้นว่า undefined แทน... เอ้าเป็นไปได้ไงมันต้อง error สิฟ๊ะ ตอนนี้ทุกคนกำลัง งงว่ามันเกิดขึ้น มันมีชื่อเรียกว่า lexical environment ครับ...

Lexical environment ?

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


       1. คือ ? ==> มันคือกล่องใบนึงครับที่เอาไว้เก็บ variable, function ที่จะเอาไปใช้งานใน software ของเราครับ

LexicalEnvironment = {
      Identifier:  <value>,
      Identifier:  <function object>
    }

รูปแบบมันก็จะประมาณนี้ครับ เมื่อใดก็ตามที่เราประกาศตัวแปร var a = 'name' อย่างนี้ตัวเจ้า lex จะเป็นอย่างนี้

LexicalEnvironment = {
      a:  'name',
    }

จะเห็นว่ามีการกำหนดค่าให้ a ลงไปประมาณนี้ครับ


       2. ปัญหา ? ==> แล้วเจ้า lex มันจะมีปัญหาคืออะไรก็ปรกติดีนี้น๊า ในความปรกติมีความไม่ปรกคือ ถ้าสมมุติว่าทำแบบนี้ล่ะ

   var a;
      console.log(a);
      a = "Tar";

จะเห็นว่าประกาศตัวแปรแต่ไม่ได้กำหนดค่าไปแล้วแสดงข้อความออกไปเลย มันต้อง error แน่ๆเลย แต่!! ต้องกันข้ามเลยมันจะไม่ error แต่จะเป็น undefined ดังนั้นตัวเจ้า lex จะเป็นแบบนี้คือการที่เจ้า lex เนี๊ยจะทำการกำหนดค่าให้ตัวแปรที่ประกาศไปแล้วแต่ยังไม่กำหนดค่าให้เป็น undefined ไว้ก่อน

LexicalEnvironment = {
      a: undefined,
    }

แล้วมันถึงไปกำหนดค่าไปหลังจาก console.log(a)

LexicalEnvironment = {
      a: 'Tar',
    }

นี้ก็คือการทำงานที่เรียกกันว่า Hoisting ครับ


ใช้ let & const กันกว่า


ก็ไปใช้ let & const แทนการใช้ var กันเถ๊อะ!!!!


      คงนี้ไม่พ้นกับการใช้ let & const แต่หารู้ไม่ว่าเจ้าสองตัวนี้ก็ไม่ต่างจาก var มากมันไม่ได้หนีไปจากเจ้า lex เลยแต่แค่เปลี่ยนค่ามันแค่นั้นเองแทนที่จะเป็น undefined ก็เป็น uninitialized แทน งั้นผมยกตัวอย่างดีกว่า

let a;
    console.log(a);
    a = "Tar";

ตรงตัวแปร a เจ้า lex จะเป็นแบบนี้แทน

LexicalEnvironment = {
      a: <uninitialized>
    }

ทุกคนเห็นไว้ว่ามัน make sense กว่าแทนที่จะ undefined ส๊ะอีกนะครับ เย้!! ในที่สุดผมก็เขียนเสร็จสักทีครับ สำหรับใครอยากเห็นตัวอย่างมากขึ้นไปอ่านที่ devhoy ได้เลยครับผมทิ้งไว้ข้างล่างให้นะครับ สวัสดีครับ


ปล. ที่จริงมันมีเรื่อง Execution Context และ Execution Stack อีกถ้าผมไม่ลืมผมจะมาอธิบายนะครับ ขอไปให้อ่านให้เข้าใจก่อนนะครับ


Ref:

Hoisting in Modern JavaScript

DevAhoy - hoisting