เหตุใดตัวแปรที่กำหนดทั่วโลกจึงไม่ได้ถูกกำหนดไว้ [ทำซ้ำ]

ฉันมีฟังก์ชันง่ายๆ และตัวแปรโกลบอลอยู่ที่นี่

เหตุใดจึงเป็น myname undefined และไม่ใช่สตริง "global"

var myname = "global"; // global variable
function func() {
    alert(myname); // "undefined"
    var myname = "local";
    alert(myname); // "local"
}
func();

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

และฉันจะแก้ไขสิ่งนี้อย่างไรเพื่อไม่ได้รับ undefined จากตัวแปรโกลบอล


person J Rod    schedule 26.05.2015    source แหล่งที่มา
comment
ฉันเดาว่าคุณลืม 'var' ในตัวแปรโกลบอล   -  person crc442    schedule 27.05.2015
comment
ฉันเชื่อว่า @ crc442 ถูกต้อง คุณสามารถโพสต์ข้อความแสดงข้อผิดพลาดเพื่อยืนยันได้หรือไม่?   -  person mas4    schedule 27.05.2015
comment
@ crc442 - ฉันเชื่อว่าคุณไม่รู้ว่าคุณกำลังพูดถึงอะไร   -  person Scott Selby    schedule 27.05.2015
comment
var ไม่จำเป็น และหากละเว้น มันจะแนบไปกับ window สร้างตัวแปรโกลบอล เช่นเดียวกับที่ OP ต้องการ   -  person Scott Selby    schedule 27.05.2015
comment
var บน globals เป็นทางเลือก คิดว่าไม่ใช่แนวปฏิบัติที่ดี   -  person Roberto    schedule 27.05.2015
comment
คำถามของคุณสับสนไปหมดแล้ว ฉันคิดว่า glabol เป็น globalm และ global เป็นของท้องถิ่น.... ?   -  person Andrew    schedule 27.05.2015
comment
โอ้! ฉันลืมไปเลย นั่นคือสัญชาตญาณในการดีบักของฉันที่กำลังพูดถึง ฉันขอโทษเกี่ยวกับเรื่องนั้น   -  person crc442    schedule 27.05.2015


คำตอบ (3)


คุณเพิ่งสะดุดกับ "คุณสมบัติ" ของ js ที่เรียกว่าการยก

var myname = "global"; // global variable
function func() {
    alert(myname); // "undefined"
    var myname = "local";
    alert(myname); // "local"
}
func();

ในโค้ดนี้เมื่อคุณกำหนด func คอมไพเลอร์จะดูที่เนื้อหาของฟังก์ชัน เห็นว่าคุณกำลังประกาศตัวแปรชื่อ myname

การประกาศตัวแปรและฟังก์ชัน Javascript Hoists โดยการย้ายการประกาศไปที่ด้านบนของฟังก์ชัน

เนื่องจากการยกโค้ดของคุณจึงถูกเขียนใหม่ดังต่อไปนี้

var myname = "global"; // global variable
function func() {
   var myname; //declare local variable and assign it undefined
   alert(myname); // "undefined"
   myname = "local"; // assign local var myname to "local"
   alert(myname); // "local"
}
func();

"ครอบคลุม" ตัวแปรโกลบอลนี้ หากคุณต้องการเข้าถึงตัวแปรร่วมภายในขอบเขตของฟังก์ชัน ให้ใช้คีย์เวิร์ด this

var myname = "global"; // global variable
function func() {
    var myname = "local";
    alert(this.myname); // "global"
    alert(myname); // "local"
}
func();

โปรดทราบว่าวิธีนี้ใช้ได้เฉพาะในการเรียกใช้ฟังก์ชัน ไม่ใช่เมธอดหรือตัวสร้าง เนื่องจากคีย์เวิร์ด this จะเปลี่ยนสิ่งที่ผูกไว้ตามวิธีที่คุณเรียกใช้ฟังก์ชัน

แก้ไข: เพื่อความสมบูรณ์

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

var global = this; // in global scope.
var myname = "global";
var obj = {f: function () {
    var myname = "local";
    console.log(global.myname);
}};
obj.f(); // "global"

โปรดทราบว่านี่อยู่ในตำแหน่งเมธอดและคีย์เวิร์ด this อ้างถึง obj โดยตรง ดังนั้นจึงไม่ได้กำหนด myname

person t3dodson    schedule 26.05.2015
comment
นี่คือคำตอบที่ถูกต้อง ฉันเข้าใจผิด - person Scott Selby; 27.05.2015
comment
ขอบคุณสำหรับคำอธิบาย มันสมเหตุสมผล ฉันมีคำถามหนึ่งข้อ เหตุใดการประกาศจึงถูกแยกออกจากการมอบหมายในบรรทัดที่ 3 ของฟังก์ชัน - person codingpuss; 15.02.2016
comment
การยก @codingpuss ไม่ย้ายตำแหน่งที่การมอบหมายเกิดขึ้น โดยจะคัดลอกเฉพาะตัวแปรที่จำเป็นในฟังก์ชันและประกาศไว้ที่ด้านบนสุด - person t3dodson; 27.02.2016
comment
หากสิ่งนี้อยู่ในเบราว์เซอร์ คุณสามารถใช้ตัวแปร window แทนตัวแปร global ของคุณได้ - person Solomon Ucko; 23.03.2018
comment
ว้าว นี่เป็นการออกแบบภาษาที่แย่มาก การแชโดว์ตัวแปรโดยไม่คาดคิดโดยไม่บอกผู้ใช้ การที่ใครก็ตามสามารถยืนหยัดภาษานี้ได้นั้นอยู่นอกเหนือฉัน - person Preza8; 31.07.2020
comment
@ Preza8 JS ได้รับการออกแบบในหนึ่งสัปดาห์ ฉันคิดว่ามันค่อนข้างดีเมื่อพิจารณาเรื่องนั้น - person t3dodson; 26.11.2020
comment
@ t3dodson ฉันได้ยินมาเช่นกันและแหล่งข้อมูลอื่นบอกฉันว่ามันไม่จริง แต่นั่นไม่ใช่ประเด็นหลัก ฉันไม่คิดว่านี่เป็นข้อแก้ตัวที่ถูกต้อง ตอนนี้ JS แก่กว่าหนึ่งสัปดาห์แล้ว พวกเขามีเวลามากมายที่จะแก้ไขเรื่องแบบนี้ ซึ่งเลวร้ายเกินจินตนาการ อีกสาเหตุหนึ่งที่นี่ไม่ใช่ข้อแก้ตัวที่ถูกต้องก็คือ ไม่ควรปล่อยให้ออกหลังจากทำงานไปเพียงสัปดาห์เดียว ลองนึกภาพนักออกแบบรถยนต์ บอกว่าเราออกแบบมันภายในหนึ่งสัปดาห์ ดังนั้น มันก็โอเค ที่แทบจะไม่ได้สตาร์ทเลย - person Preza8; 26.11.2020

ภายในฟังก์ชัน คุณกำลังประกาศ var myname = "local" แม้ว่าคุณจะทำกลางเมธอด แต่ตัวแปรนั้นมีขอบเขตของฟังก์ชัน ดังนั้นมันจึงเป็นของฟังก์ชันทั้งหมด แม้แต่โค้ดที่อยู่ด้านบนด้วยซ้ำ

ดังนั้นค่าของตัวแปรโลคัลจึงไม่ได้ถูกกำหนดไว้ก่อนหน้าบรรทัดนั้น และมีค่าอยู่หลัง แต่ไม่มีผู้ใดแตะต้องตัวแปรโกลบอล

person Joe Enos    schedule 26.05.2015
comment
ฉันไม่คิดว่าคำตอบส่วนนี้ของคุณแม่นยำ: ดังนั้นค่าของตัวแปรโลคัลจึงไม่ได้ถูกกำหนดไว้ก่อนหน้าบรรทัดนั้น .... คำสั่ง var จะถูกย้ายไปด้านบนในจาวาสคริปต์ (ยก) ดังนั้นจึงถูกดำเนินการก่อนโค้ดอื่น ๆ ภายใน คะแนน (ในกรณีนี้คือฟังก์ชัน) - person codingpuss; 15.02.2016
comment
ในฐานะโปรแกรมเมอร์หน้าใหม่ ฉันไม่สามารถหาวิธีแก้ปัญหานี้ได้ ไม่ว่าฉันจะอ่านคำตอบเหล่านี้ไปกี่คำตอบก็ตาม ปัญหาคือฉันถือว่าทุกครั้งที่ต้องการแก้ไขตัวแปร ฉันต้องขึ้นต้นบรรทัดด้วย var (เช่น var myVariable = 1;, var myVariable = myVariable + 3;) แต่ในความเป็นจริง คุณควรใส่ var ในครั้งแรกที่คุณเริ่มต้นตัวแปรเท่านั้น หลังจากนั้น คุณจะต้องเริ่มบรรทัดด้วยชื่อตัวแปรแล้วปล่อย var (เช่น var myVariable = 1;, myVariable = myVariable + 3;) (ไม่เช่นนั้นจะเกิดปัญหาเช่นนี้ขึ้น) - person gamingexpert13; 31.03.2021

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

อันด้านล่างนี้ใช้งานได้เพราะเหนือการแจ้งเตือนที่คุณให้ไว้

person Andrew    schedule 26.05.2015