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: