ความแตกต่างระหว่างไวยากรณ์การประกาศตัวแปรใน Javascript (รวมถึงตัวแปรทั่วโลก)?


292

มีความแตกต่างระหว่างการประกาศตัวแปร:

var a=0; //1

...ทางนี้:

a=0; //2

...หรือ:

window.a=0; //3

อยู่ในขอบเขตทั่วโลกหรือไม่


2
AFAIK var a = 0; ไม่ทำงานใน IE เมื่อเข้าถึงตัวแปรผ่านไฟล์ js ภายนอกอื่นซึ่งประกาศในไฟล์ js อื่น
Aivan Monceller

ฉันไม่ทราบเกี่ยวกับ window.a แต่อีก 2 วิธีเหมือนกันในขอบเขตทั่วโลก
โปรแกรมเมอร์

1
@AivanMonceller จริงเหรอ? ลิงค์โปรด
Raynos

@ Raynos ฉันพบมันในเว็บไซต์ของฉันเอง IE6 จะเฉพาะเจาะจง ฉันไม่สามารถรับค่า enum ของฉันให้ปรากฏซึ่งอยู่ในไฟล์ js ภายนอกและฉันกำลังอ้างอิงว่าเป็น javascript แบบอินไลน์ในไฟล์ html
Aivan Monceller

@Ashwini ในขอบเขตส่วนกลางหน้าต่างจะเป็นวัตถุส่วนกลาง (ในเบราว์เซอร์) var a = 1; console.log (ก); console.log (win
leebriggs

คำตอบ:


557

ใช่มีความแตกต่างอยู่สองอย่างแม้ว่าในแง่การปฏิบัติพวกมันมักจะไม่ใช่เรื่องใหญ่

มีวิธีที่สี่และ ES2015 (ES6) มีอีกสองวิธี ฉันได้เพิ่มวิธีที่สี่ในตอนท้าย แต่แทรกวิธี ES2015 หลังจาก # 1 (คุณจะเห็นว่าทำไม) ดังนั้นเราจึงมี:

var a = 0;     // 1
let a = 0;     // 1.1 (new with ES2015)
const a = 0;   // 1.2 (new with ES2015)
a = 0;         // 2
window.a = 0;  // 3
this.a = 0;    // 4

คำอธิบายเหล่านั้นอธิบาย

# 1 var a = 0;

สิ่งนี้สร้างตัวแปรทั่วโลกซึ่งเป็นทรัพย์สินของวัตถุทั่วโลกซึ่งเราเข้าถึงได้เช่นเดียวwindowกับในเบราว์เซอร์ (หรือผ่านthisขอบเขตทั่วโลกในรหัสที่ไม่เข้มงวด) ไม่เหมือนกับคุณสมบัติอื่น ๆ คุณสมบัตินี้ไม่สามารถลบผ่านdeleteได้

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

การรวม (ตัวแปร) ถูกกำหนดไว้ก่อนที่บรรทัดแรกของการเรียกใช้รหัส (ดู "เมื่อvarเกิดขึ้น" ด้านล่าง)

โปรดทราบว่าใน IE8 และก่อนหน้านี้คุณสมบัติที่สร้างขึ้นwindowไม่สามารถนับได้ (ไม่แสดงในfor..inคำสั่ง) ใน IE9, Chrome, Firefox และ Opera มันนับได้


# 1.1 let a = 0;

สิ่งนี้สร้างตัวแปรส่วนกลางซึ่งไม่ใช่คุณสมบัติของวัตถุทั่วโลก นี่คือสิ่งใหม่ ณ ES2015

ในข้อกำหนดคุณสมบัติจะสร้างการเชื่อมโยงตัวระบุบนเร็กคอร์ดสภาวะแวดล้อมที่ประกาศสำหรับสภาพแวดล้อมแบบโกลบอลแทนอ็อบเจ็กต์ Environment Record สภาพแวดล้อมโลกที่ไม่ซ้ำกันในการมีสิ่งแวดล้อมแยกบันทึกหนึ่งสำหรับทุกสิ่งเก่าที่ไปบนวัตถุทั่วโลก (the วัตถุสิ่งแวดล้อม Record) และอื่น ๆ สำหรับทุกสิ่งที่ใหม่ ( let, constและฟังก์ชั่นที่สร้างขึ้นโดยclass) ที่ทำไม่ได้ ไปที่วัตถุระดับโลก

การรวมจะถูกสร้างขึ้นก่อนที่โค้ดทีละขั้นตอนในบล็อกที่ล้อมรอบจะถูกดำเนินการ (ในกรณีนี้ก่อนที่จะรันโค้ดทั่วโลก) แต่จะไม่สามารถเข้าถึงได้ในทางใด ๆ จนกว่าการดำเนินการทีละขั้นตอนจะมาถึงletคำสั่ง เมื่อดำเนินการถึงletคำสั่งตัวแปรจะสามารถเข้าถึงได้ (ดูที่ "เมื่อใดletและconstเกิดขึ้น" ด้านล่าง)


# 1.2 const a = 0;

สร้างค่าคงที่ส่วนกลางซึ่งไม่ใช่คุณสมบัติของวัตถุทั่วโลก

constเหมือนกับletว่าคุณต้องระบุ initializer ( = valueส่วน) และคุณไม่สามารถเปลี่ยนค่าของค่าคงที่ได้เมื่อมันถูกสร้างขึ้น ภายใต้หน้าปกมันเหมือนกับletแต่มีการตั้งค่าสถานะบนการเชื่อมโยงตัวระบุว่าค่าไม่สามารถเปลี่ยนแปลงได้ การใช้constสามสิ่งสำหรับคุณ:

  1. ทำให้เป็นข้อผิดพลาดในการวิเคราะห์คำหากคุณพยายามกำหนดให้กับค่าคงที่
  2. บันทึกลักษณะที่ไม่เปลี่ยนแปลงของโปรแกรมเมอร์อื่น ๆ
  3. ช่วยให้เครื่องมือเพิ่มประสิทธิภาพ JavaScript บนพื้นฐานที่ว่ามันจะไม่เปลี่ยนแปลง

# 2 a = 0;

นี้จะสร้างสถานที่ให้บริการบนวัตถุทั่วโลกได้โดยปริยาย เนื่องจากเป็นคุณสมบัติปกติคุณสามารถลบได้ ฉันไม่แนะนำให้ทำอย่างนี้มันอาจจะไม่ชัดเจนสำหรับใครก็ตามที่อ่านรหัสของคุณในภายหลัง หากคุณใช้โหมดเข้มงวดของ ES5 การทำเช่นนี้ (การกำหนดให้กับตัวแปรที่ไม่มีอยู่) เป็นข้อผิดพลาด เป็นหนึ่งในหลายเหตุผลที่ต้องใช้โหมดเข้มงวด

และน่าสนใจอีกครั้งใน IE8 และก่อนหน้านี้คุณสมบัติที่สร้างขึ้นไม่สามารถนับได้ (ไม่แสดงในfor..inคำสั่ง) มันแปลกมากโดยเฉพาะอย่างยิ่ง # 3 ด้านล่าง


# 3 window.a = 0;

สิ่งนี้สร้างคุณสมบัติบนวัตถุโกลบอลอย่างชัดเจนโดยใช้windowโกลบอลที่อ้างถึงอ็อบเจ็กต์โกลบอล (บนเบราว์เซอร์สภาพแวดล้อมที่ไม่ใช่เบราว์เซอร์บางตัวมีตัวแปรโกลบอลที่เทียบเท่ากันเช่นglobalบน NodeJS) เนื่องจากเป็นคุณสมบัติปกติคุณสามารถลบได้

คุณสมบัตินี้สามารถนับได้บน IE8 และรุ่นก่อนหน้าและบนเบราว์เซอร์อื่น ๆ ที่ฉันได้ลอง


# 4 this.a = 0;

เหมือน # 3 ยกเว้นเรากำลังอ้างอิงวัตถุทั่วโลกผ่านทางแทนของโลกthis windowสิ่งนี้จะไม่ทำงานในโหมดเข้มงวด แต่เนื่องจากในรหัสสากลของโหมดเข้มงวดthisไม่ได้มีการอ้างอิงไปยังวัตถุทั่วโลก (มีค่าundefinedแทน)


การลบคุณสมบัติ

ผมหมายถึงอะไรโดย "ลบ" หรือ "ลบ" a? ตรงที่: การลบคุณสมบัติ (ทั้งหมด) ผ่านdeleteคำหลัก:

window.a = 0;
display("'a' in window? " + ('a' in window)); // displays "true"
delete window.a;
display("'a' in window? " + ('a' in window)); // displays "false"

deleteเอาคุณสมบัติออกจากวัตถุอย่างสมบูรณ์ คุณไม่สามารถทำเช่นนั้นได้ด้วยคุณสมบัติที่เพิ่มลงในwindowทางอ้อมvarสิ่งdeleteนั้นอาจถูกละเว้นอย่างเงียบ ๆ หรือส่งข้อยกเว้น (ขึ้นอยู่กับการใช้งาน JavaScript และไม่ว่าคุณจะอยู่ในโหมดเข้มงวด)

คำเตือน : IE8 อีกครั้ง (และคาดว่าก่อนหน้านี้และ IE9-IE11 ในโหมด "ความเข้ากันได้" ที่ใช้งานไม่ได้): มันจะไม่ยอมให้คุณลบคุณสมบัติของwindowวัตถุแม้ว่าคุณจะได้รับอนุญาตก็ตาม ที่แย่กว่านั้นคือจะมีข้อยกเว้นเมื่อคุณลอง ( ลองการทดสอบนี้ใน IE8 และในเบราว์เซอร์อื่น ๆ ) ดังนั้นเมื่อลบออกจากwindowวัตถุคุณจะต้องป้องกัน:

try {
    delete window.prop;
}
catch (e) {
    window.prop = undefined;
}

undefinedที่พยายามที่จะลบคุณสมบัติและถ้ายกเว้นจะโยนมันจะเป็นสิ่งที่ดีที่สุดต่อไปและกำหนดสถานที่ให้บริการ

นี้เพียงนำไปใช้กับwindowวัตถุและเฉพาะ (เท่าที่ฉันรู้) เพื่อ IE8 และก่อนหน้านี้ (หรือ IE9-IE11 ในเสียโหมด "การทำงานร่วมกัน") เบราว์เซอร์อื่นนั้นใช้ได้ดีกับการลบwindowคุณสมบัติโดยขึ้นอยู่กับกฎข้างต้น


เมื่อvarเกิดขึ้น

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

อาจทำให้สับสนได้ดังนั้นลองมาดูกัน:

display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo);          // displays "undefined"
display("bar in window? " + ('bar' in window)); // displays "false"
display("window.bar = " + window.bar);          // displays "undefined"
var foo = "f";
bar = "b";
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo);          // displays "f"
display("bar in window? " + ('bar' in window)); // displays "true"
display("window.bar = " + window.bar);          // displays "b"

ตัวอย่างสด:

ในขณะที่คุณสามารถมองเห็นสัญลักษณ์fooถูกกำหนดไว้ก่อนบรรทัดแรก แต่สัญลักษณ์barไม่ได้ ในกรณีที่var foo = "f";คำสั่งนั้นมีสองสิ่งจริง ๆ : การกำหนดสัญลักษณ์ซึ่งเกิดขึ้นก่อนที่จะรันโค้ดบรรทัดแรก และทำการกำหนดสัญลักษณ์นั้นซึ่งเกิดขึ้นที่บรรทัดนั้นอยู่ในโฟลว์ทีละขั้นตอน สิ่งนี้เรียกว่า " varhoisting" เนื่องจากชิ้นvar fooส่วนถูกย้าย ("hoisted") ไปยังด้านบนของขอบเขต แต่ชิ้นfoo = "f"ส่วนนั้นจะอยู่ในตำแหน่งเดิม (ดูแย่เข้าใจผิดvarในบล็อกเล็ก ๆ ของฉันโลหิตจาง)


เมื่อใดletและconstเกิดขึ้น

letและconstแตกต่างจากvarในสองวิธี วิธีที่เกี่ยวข้องกับคำถามคือแม้ว่าการเชื่อมโยงที่กำหนดจะถูกสร้างขึ้นก่อนที่จะรันรหัสทีละขั้นตอน แต่ก็ไม่สามารถเข้าถึงได้จนกว่าจะถึงคำสั่งletหรือconstคำสั่ง

ดังนั้นขณะที่สิ่งนี้ทำงาน:

display(a);    // undefined
var a = 0;
display(a);    // 0

สิ่งนี้ทำให้เกิดข้อผิดพลาด:

display(a);    // ReferenceError: a is not defined
let a = 0;
display(a);

อีกสองวิธีการที่letและconstแตกต่างจากvarที่ไม่ได้จริงๆที่เกี่ยวข้องกับคำถามคือ:

  1. varมักจะนำไปใช้กับบริบทของการดำเนินการทั้งหมด (ทั่วโลกรหัสหรือรหัสผ่านของฟังก์ชั่นในการทำงานที่ปรากฏ) แต่letและconstใช้เฉพาะภายในบล็อกที่พวกเขาปรากฏ นั่นคือvarมีฟังก์ชั่น (หรือทั่วโลก) ขอบเขต แต่letและconstมีขอบเขตบล็อก

  2. การทำซ้ำvar aในบริบทเดียวกันนั้นไม่เป็นอันตราย แต่ถ้าคุณมีlet a(หรือconst a) การมีอีกอันlet aหรือ a const aหรือ a var aเป็นข้อผิดพลาดทางไวยากรณ์

นี่คือตัวอย่างที่แสดงให้เห็นว่าletและconstมีผลทันทีในบล็อกของพวกเขาก่อนที่โค้ดใด ๆ ในบล็อกนั้นจะทำงาน แต่ไม่สามารถเข้าถึงได้จนกว่าจะมีคำสั่งletหรือconst

var a = 0;
console.log(a);
if (true)
{
  console.log(a); // ReferenceError: a is not defined
  let a = 1;
  console.log(a);
}

โปรดทราบว่าครั้งที่สองconsole.logล้มเหลวแทนที่จะเข้าใช้aจากนอกบล็อก


นอกหัวข้อ: หลีกเลี่ยงการถ่วงวัตถุส่วนกลาง ( window)

windowวัตถุได้รับมากรกมากที่มีคุณสมบัติ เมื่อใดก็ตามที่เป็นไปได้ขอแนะนำไม่ให้เพิ่มความยุ่งเหยิง แต่ห่อขึ้นสัญลักษณ์ในแพคเกจเล็ก ๆ น้อย ๆ และการส่งออกที่มากที่สุดสัญลักษณ์หนึ่งไปยังwindowวัตถุ (ฉันมักจะไม่ส่งออกสัญลักษณ์ใด ๆไปยังwindowวัตถุ) คุณสามารถใช้ฟังก์ชั่นเพื่อบรรจุโค้ดทั้งหมดของคุณเพื่อให้มีสัญลักษณ์ของคุณและฟังก์ชั่นนั้นอาจไม่ระบุตัวตนหากคุณต้องการ:

(function() {
    var a = 0; // `a` is NOT a property of `window` now

    function foo() {
        alert(a);   // Alerts "0", because `foo` can access `a`
    }
})();

ในตัวอย่างนั้นเรากำหนดฟังก์ชั่นและให้มันดำเนินการทันที ( ()ในตอนท้าย)

ฟังก์ชั่นใช้วิธีนี้เรียกว่าบ่อยฟังก์ชั่นการกำหนดขอบเขต ฟังก์ชั่นที่กำหนดไว้ในฟังก์ชั่นการกำหนดขอบเขตสามารถเข้าถึงตัวแปรที่กำหนดไว้ในฟังก์ชั่นการกำหนดขอบเขตเพราะพวกเขาปิดข้อมูลนั้น (ดู: การปิดไม่ซับซ้อนในบล็อกเล็ก ๆ ของฉันเกี่ยวกับโลหิตจาง)


ฉันจะทำอย่างไรwindow['a']=0เพื่อให้ชัดเจนฉันกำลังใช้หน้าต่างเป็นแผนที่? เป็นwindowพิเศษเช่นเบราว์เซอร์ที่บางคนไม่อนุญาตให้นี้และบังคับให้ผมใช้window.a?
Jayen

หมายเหตุหนึ่งใน# 3ที่น่าจะคุ้มค่าในการชี้แจง: window.a = 0;ใช้ได้เฉพาะในสภาพแวดล้อมของเบราว์เซอร์และตามแบบแผนเท่านั้น การเชื่อมออบเจกต์โกลบอลกับตัวแปรที่ชื่อwindowไม่ได้อยู่ใน ES Spec และจะไม่ทำงานเช่น V8 หรือ Node.js ในขณะที่this.a = 0;(เมื่อเรียกใช้ในบริบทการเรียกใช้งานโกลบอล) จะทำงานในสภาพแวดล้อมใด ๆ เนื่องจากสเป็คไม่ได้ระบุ จะต้องมีวัตถุระดับโลก หากการห่อโค้ดของคุณใน IIFE ในส่วนหัวข้อนอกคุณสามารถส่งthisเป็นพารามิเตอร์ที่มีชื่อwindowหรือglobalเพื่อรับการอ้างอิงโดยตรงไปยังวัตถุทั่วโลก
Sherlock_HJ

@Sherlock_HJ: ฉันได้เพิ่ม "ในเบราว์เซอร์" นั่นคือก่อนหน้านี้ในคำตอบเช่นกัน แต่ฉันเพิ่มไว้ในกรณีที่ผู้คนข้ามไปที่ มันอยู่ในสเป็คตอนนี้ ; ในขณะที่ผ่านไปคุณจะไม่พบเบราว์เซอร์ที่ไม่สามารถทำได้ ฉันประหลาดใจเล็กน้อยก็ไม่ได้อยู่ในภาคผนวกข
TJ Crowder

@TJCrowder ดังนั้นตัวแปรทั่วโลกที่ประกาศด้วยvar a = 0;จะกลายเป็นสมบัติของวัตถุทั่วโลกโดยอัตโนมัติ ถ้าฉันประกาศvar b = 0;ในการประกาศฟังก์ชั่นมันจะเป็นคุณสมบัติของวัตถุต้นแบบบ้างหรือไม่?
ezpresso

@ezpresso: ไม่และใช่ พวกเขากลายเป็นคุณสมบัติของวัตถุ ( EnvironmentRecordของVariableEnvironmentของExecutionContextที่ปรากฏรายละเอียดที่นี่และที่นี่ ) แต่ไม่มีวิธีเข้าถึงวัตถุนั้นโดยตรงจากรหัสโปรแกรม
TJ Crowder

40

ทำให้มันง่าย:

a = 0

รหัสด้านบนให้ตัวแปรขอบเขตทั่วโลก

var a = 0;

รหัสนี้จะให้ตัวแปรที่จะใช้ในขอบเขตปัจจุบันและภายใต้มัน

window.a = 0;

โดยทั่วไปจะเหมือนกับตัวแปรทั่วโลก


งบของคุณ"รหัสดังกล่าวข้างต้นให้ตัวแปรขอบเขตทั่วโลก"และ"รหัสนี้จะให้ตัวแปรที่จะใช้ในขอบเขตปัจจุบันและภายใต้มัน"ที่นำมาร่วมกันแสดงให้เห็นว่าคุณไม่สามารถใช้บรรทัดแรกและการเข้าถึงa ภายใต้ขอบเขตปัจจุบัน คุณสามารถ. นอกจากนี้การใช้ "ตัวแปรทั่วโลก" ของคุณนั้นค่อนข้างแย่ไปกว่าสองตำแหน่งที่คุณพูดว่า "ตัวแปรทั่วโลก" นั้นไม่ได้อยู่ในระดับโลกมากกว่าสถานที่ที่คุณไม่ได้พูด
TJ Crowder

โกลบอลเองหมายความว่าคุณสามารถเข้าถึง / อ่าน / เขียนตัวแปรได้ทุกที่รวมถึงสถานที่ที่ฉันพูดถึงขอบเขตปัจจุบันซึ่งชัดเจนมาก และถ้าคุณแนะนำ window.a และ 'a' จะไม่เป็นส่วนกลางในสคริปต์คุณจะผิด 100%
Umair Jabbar

3
@Umair: "global global หมายความว่าคุณสามารถเข้าถึง / อ่าน / เขียนตัวแปรได้ทุกที่"ขวา อีกครั้งคุณดูเหมือนจะเรียกคนแรกและคนสุดท้ายว่าเป็น "โลก" มากกว่ากลางซึ่งแน่นอนว่ามันไม่ใช่
TJ Crowder

4
ตรงกลางถือว่าใช้งานภายในฟังก์ชั่นทั้งหมดจะเหมือนกันหากใช้ภายใต้ขอบเขตหลัก โดยใช้ฟังก์ชั่นภายใน var ถูกสมมติฐานของฉัน
Umair จับบาร์

4
@Umair: "การใช้ var ภายในฟังก์ชั่นเป็นข้อสันนิษฐานของฉัน"อ่าโอเค แต่นั่นไม่ใช่คำถาม คำถามอย่างชัดเจนกล่าวว่า"ในขอบเขตทั่วโลก" หากคุณจะเปลี่ยนสมมติฐาน (ซึ่งยุติธรรมเพียงพอเพื่อขยายและอธิบายประเด็นทั่วไปเพิ่มเติม) คุณจะต้องชัดเจนว่าเป็นสิ่งที่คุณทำในคำตอบของคุณ
TJ Crowder

10
<title>Index.html</title>
<script>
    var varDeclaration = true;
    noVarDeclaration = true;
    window.hungOnWindow = true;
    document.hungOnDocument = true;
</script>
<script src="external.js"></script>

/* external.js */

console.info(varDeclaration == true); // could be .log, alert etc
// returns false in IE8

console.info(noVarDeclaration == true); // could be .log, alert etc
// returns false in IE8

console.info(window.hungOnWindow == true); // could be .log, alert etc
// returns true in IE8

console.info(document.hungOnDocument == true); // could be .log, alert etc
// returns ??? in IE8 (untested!)  *I personally find this more clugy than hanging off window obj

มีวัตถุส่วนกลางที่ vars ทั้งหมดถูกพักการใช้งานเป็นค่าเริ่มต้นหรือไม่? เช่น: 'globals.noVar declaration'


การสำรวจที่ดีมาก คู่มือที่ชัดเจนในการใช้window.*การประกาศ การประกาศนี้ดูปลอดภัยที่สุดต่อการคัดลอกโค้ดของคุณและชัดเจนด้วย
Dan

7

ได้รับคำตอบที่ยอดเยี่ยมของTJ Crowder : ( Off-topic: หลีกเลี่ยงความยุ่งเหยิงwindow )

นี่คือตัวอย่างของความคิดของเขา:

html

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="init.js"></script>
    <script type="text/javascript">
      MYLIBRARY.init(["firstValue", 2, "thirdValue"]);
    </script>
    <script src="script.js"></script>
  </head>

  <body>
    <h1>Hello !</h1>
  </body>    
</html>

init.js (ตามคำตอบนี้ )

var MYLIBRARY = MYLIBRARY || (function(){
    var _args = {}; // private

    return {
        init : function(Args) {
            _args = Args;
            // some other initialising
        },
        helloWorld : function(i) {
            return _args[i];
        }
    };
}());

script.js

// Here you can use the values defined in the html as if it were a global variable
var a = "Hello World " + MYLIBRARY.helloWorld(2);

alert(a);

นี่คือplnkr หวังว่ามันจะช่วย!


5

ในขอบเขตทั่วโลกไม่มีความแตกต่างทางความหมาย

แต่คุณควรหลีกเลี่ยงa=0เพราะตั้งค่าเป็นตัวแปรที่ไม่ได้ประกาศ

ใช้การปิดเพื่อหลีกเลี่ยงการแก้ไขขอบเขตทั่วโลกเลย

(function() {
   // do stuff locally

   // Hoist something to global scope
   window.someGlobal = someLocal
}());

ใช้การปิดและยกระดับขอบเขตเสมอเมื่อจำเป็นอย่างยิ่ง คุณควรใช้การจัดการเหตุการณ์แบบอะซิงโครนัสเพื่อการสื่อสารส่วนใหญ่ของคุณ

ตามที่ @AvianMoncellor กล่าวถึงว่ามีข้อผิดพลาด IE ที่มีvar a = fooเพียงการประกาศระดับโลกสำหรับขอบเขตไฟล์ นี่เป็นปัญหาของล่ามที่เสียชื่อเสียงของ IE ข้อผิดพลาดนี้ฟังดูคุ้นหูดังนั้นอาจเป็นเรื่องจริง

ดังนั้นติด window.globalName = someLocalpointer


2
"ในขอบเขตทั่วโลกไม่มีความแตกต่างทางความหมาย" อันที่จริงมีความแตกต่างความหมายอย่างมากกลไกที่สถานที่ให้บริการที่ได้รับการกำหนดไว้จะแตกต่างกันอย่างสมบูรณ์ - แต่ในแง่การปฏิบัติมันเดือดลงไปเพียงเล็ก ๆที่เกิดขึ้นจริงที่แตกต่างกัน (ในการที่คุณไม่สามารถ) deletevar
TJ Crowder

@TJ Crowder ฉันไม่รู้ ฉันคิดว่าการประกาศตัวแปรเป็นการตั้งค่าคุณสมบัติบนวัตถุตัวแปร ไม่ทราบว่าไม่สามารถลบได้
Raynos

ได้. varพวกเขากำลังที่กำหนดไว้ก่อนหน้านี้ยังถ้าคุณใช้ พวกมันเป็นเพียงกลไกที่แตกต่างอย่างสิ้นเชิงที่มีผลการปฏิบัติเหมือนกัน :-)
TJ Crowder

@TJ Crowder ฉันลืมพูดถึงvarกระโดดข้ามขอบเขต
Raynos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.