ปรากฏการณ์นี้เป็นที่รู้จักกันในนามJavaScript Hoisting
คุณไม่ได้เข้าถึงตัวแปรส่วนกลางในฟังก์ชันของคุณ ณ จุดใด คุณจะเข้าถึงvalue
ตัวแปรภายในเครื่องเท่านั้น
รหัสของคุณเทียบเท่ากับสิ่งต่อไปนี้:
var value = 10;
function test() {
var value;
console.log(value);
value = 20;
console.log(value);
}
test();
ยังแปลกใจที่คุณได้รับundefined
?
คำอธิบาย:
นี่คือสิ่งที่โปรแกรมเมอร์ JavaScript ทุกคนต้องเจอไม่ช้าก็เร็ว พูดง่ายๆว่าตัวแปรใดก็ตามที่คุณประกาศจะถูกยกขึ้นไปอยู่อันดับต้น ๆ ของการปิดในพื้นที่ของคุณ ดังนั้นแม้ว่าคุณจะประกาศตัวแปรของคุณหลังจากตัวแรกconsole.log
โทรแต่ก็ยังถือว่าคุณได้ประกาศไว้ก่อนหน้านั้น
อย่างไรก็ตามมีเพียงส่วนการประกาศเท่านั้นที่ถูกยกขึ้น ในทางกลับกันงานที่ได้รับมอบหมายไม่ใช่
ดังนั้นเมื่อคุณโทรครั้งแรกconsole.log(value)
คุณกำลังอ้างถึงตัวแปรที่ประกาศในเครื่องของคุณซึ่งยังไม่ได้กำหนดอะไรเลย ด้วยเหตุนี้undefined
.
นี่คืออีกตัวอย่างหนึ่ง :
var test = 'start';
function end() {
test = 'end';
var test = 'local';
}
end();
alert(test);
คุณคิดว่าสิ่งนี้จะแจ้งเตือนอะไร ไม่อย่าเพิ่งอ่านลองคิดดู มูลค่าของtest
อะไร?
ถ้าคุณพูดอะไรนอกเหนือจากstart
นั้นคุณคิดผิด รหัสข้างต้นเทียบเท่ากับสิ่งนี้:
var test = 'start';
function end() {
var test;
test = 'end';
test = 'local';
}
end();
alert(test);
เพื่อไม่ให้ตัวแปร global ได้รับผลกระทบ
อย่างที่คุณเห็นไม่ว่าคุณจะวางการประกาศตัวแปรไว้ที่ใดก็ตามการประกาศตัวแปรจะถูกยกขึ้นไปด้านบนของการปิดในพื้นที่ของคุณเสมอ
หมายเหตุด้านข้าง:
นอกจากนี้ยังใช้กับฟังก์ชัน
พิจารณาโค้ดส่วนนี้ :
test("Won't work!");
test = function(text) { alert(text); }
ซึ่งจะทำให้คุณมีข้อผิดพลาดในการอ้างอิง:
Uncaught ReferenceError: ไม่มีการกำหนดการทดสอบ
สิ่งนี้ทำให้นักพัฒนาจำนวนมากไม่พอใจเนื่องจากโค้ดชิ้นนี้ใช้งานได้ดี:
test("Works!");
function test(text) { alert(text); }
เหตุผลนี้ตามที่ระบุไว้เนื่องจากส่วนที่ได้รับมอบหมายไม่ได้ถูกยกขึ้น ดังนั้นในตัวอย่างแรกเมื่อtest("Won't work!")
ถูกเรียกใช้ไฟล์test
ตัวแปรได้ถูกประกาศแล้ว แต่ยังไม่ได้กำหนดฟังก์ชันให้
ในตัวอย่างที่สองเราไม่ได้ใช้การกำหนดตัวแปร แต่เรากำลังใช้ไวยากรณ์การประกาศฟังก์ชันที่เหมาะสมซึ่งจะทำให้ฟังก์ชันถูกยกขึ้นอย่างสมบูรณ์
Ben Cherryได้เขียนบทความที่ยอดเยี่ยมเกี่ยวกับเรื่องนี้โดยมีชื่อว่าJavaScript Scoping and Hoistingอย่างเหมาะสม
อ่านมัน. จะให้ภาพรวมโดยละเอียด