มีเหตุผลใดที่จะใช้คำหลัก“ var” ใน ES6?


261

คำแนะนำของ Babel สำหรับ ES6พูดว่า:

letvarเป็นใหม่

เห็นได้ชัดว่าแตกต่างเพียงว่าvarได้รับการกำหนดขอบเขตในปัจจุบันฟังก์ชั่นในขณะที่letได้รับการกำหนดขอบเขตในปัจจุบันบล็อก มีตัวอย่างที่ดีใน คำตอบนี้

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

ดังนั้นสัญชาตญาณของฉันคือหยุดใช้varทั้งหมดเมื่อเขียนรหัส ES6

คำถามของฉันคือฉันผิดเกี่ยวกับเรื่องนี้? มีกรณีที่ถูกต้องตามกฎหมายที่varจะได้รับความนิยมมากกว่าlet?


3
ฉันยังไม่ได้ลองเลย (เนื่องจากฉันยังไม่ได้เขียนรหัส ES6) แต่ดูเหมือนว่าการใช้varเป็นตัวบ่งชี้ที่มีสติว่าตัวแปรนี้มีจุดมุ่งหมายเพื่อกำหนดขอบเขตให้กับฟังก์ชั่นทั้งหมดอาจเป็นการประชุมที่มีประโยชน์ .
jfriend00

10
หากคุณใส่letคำแถลงที่ด้านบนสุดของฟังก์ชั่นฉันคิดว่ามันชัดเจนว่าคุณตั้งใจจะกำหนดขอบเขตให้กับฟังก์ชันทั้งหมด ฉันไม่คิดว่าการใช้varทำให้ชัดเจนกว่าการค้นหาที่ด้านบน
callum

11
สุจริตฉันเชื่อว่าเหตุผลเดียวที่varยังคงมีอยู่คือความเข้ากันได้ย้อนหลัง หากไม่ใช่เพราะสิ่งนั้นพวกเขาจะลบออกvarไปโดยสิ้นเชิงหรือไม่เคยแนะนำมาletก่อนเลยแทนที่จะเปลี่ยนความหมายของvarสิ่งที่มันควรจะเป็นมาตลอด
Jörg W Mittag

2
@ RayToal ฉันเห็นด้วยกับ 97% ของสิ่งที่ Kyle Simpson พูด แต่เหตุผลที่ทำให้เขาใช้งานต่อไปนั้นvarดูผอมไปสำหรับฉันและไม่เพียงพอที่จะรับประกันว่ามีตัวแปรชนิดที่สามที่กระโดดไปมา คุณสามารถกำหนดขอบเขต a letให้กับฟังก์ชั่นทั้งหมดได้ง่ายๆโดยวางไว้ที่ด้านบนสุดของฟังก์ชั่นซึ่งมีความตั้งใจชัดเจนกว่าการเขียนvarในบล็อก (เพื่อให้สามารถยกออกจากบล็อกนั้นเพื่อให้คุณสามารถใช้มันนอกบล็อกได้ - แปลก) เขาเตือนว่าถ้าคุณกำหนดขอบเขตให้letกับฟังก์ชั่นแล้ว "เป็นเพียงตำแหน่งที่ส่งสัญญาณความแตกต่างมากกว่าไวยากรณ์" แต่ฉันคิดว่านั่นเป็นสิ่งที่ดี
callum

2
@ RayToal ฉันก็อ่านบทความนั้น (ก่อนที่จะอ่านการสนทนานี้) และฉันก็ผิดหวังมากสำหรับกรณีที่อ่อนแอของvarเขา ตัวอย่างที่เขานำเสนอเพื่อการรักษาvarดูเหมือนจะถูกจัดทำขึ้น - และมีพื้นฐานมาจากข้อผิดพลาดการเข้ารหัสที่รุนแรง จะดีกว่ามากหากพบข้อผิดพลาดและถูกบังคับให้แก้ไขข้อผิดพลาดดังกล่าวมากกว่าใช้ฟังก์ชั่นภาษาที่ปล่อยให้มันหนีไป! มีอะไรต่อไปแนะนำให้ห่อทุกอย่างด้วยการลอง / จับเพื่อป้องกันการล่ม ส่วนที่เหลือของลิงค์นั้นดี แต่ฉันไม่เห็นด้วยกับส่วนนั้น
Mörre

คำตอบ:


217

ดั๊กครอกกล่าวถึงletที่จุดนี้ในการพูดคุยของเขา " ส่วนที่ดีกว่า "

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

var อาจยังมีประโยชน์ในกรณีที่รุนแรงเช่นรหัสที่สร้างด้วยเครื่อง แต่ฉันก็พยายามอย่างหนัก

( constยังเป็นใหม่และมีการปิดกั้นขอบเขต. หลังจากที่let x = {'hi': 'SE'}คุณสามารถกำหนดไปxในขณะที่หลังจากที่const y = xคุณไม่สามารถโอนสิทธิการy. ที่มักจะ preferrable เพราะมันช่วยให้อะไรบางอย่างจากตั้งใจเปลี่ยนออกมาจากใต้คุณ. แต่การที่จะมีความชัดเจนคุณยังสามารถปรับเปลี่ยนวัตถุy.hi = 'SO'เว้นแต่คุณ ตรึงไว้)

แนบเนียนแสดงผลของคุณเป็นที่เหมาะสมสำหรับ ES6: นำมาใช้และlet หยุดใช้constvar

(ในการทำงานของ "ดีกว่าส่วนอื่น"ดั๊กกล่าวว่าเหตุผลที่===ถูกเพิ่มเข้ามามากกว่าการแก้ไขปัญหาของ== . ==ผลิตบางส่วน "ที่น่าแปลกใจ" ผลดังนั้นเพียงแค่นำมาใช้===.)


ตัวอย่างการเปิดเผย

Mozilla Developer Networkให้ตัวอย่างที่varไม่ทำงานตามที่ตั้งใจ ตัวอย่างของพวกเขาคือสิ่งที่เหมือนจริงที่กำหนดonclickตัวจัดการในหน้าเว็บ นี่คือกรณีทดสอบขนาดเล็ก:

var a = [];
(function () {
   'use strict';
   for (let i = 0; i < 5; ++i) { // *** `let` works as expected ***
     a.push( function() {return i;} );
   }
} ());
console.log(a.map( function(f) {return f();} ));
// prints [0, 1, 2, 3, 4]

// Start over, but change `let` to `var`.
// prints [5, 5, 5, 5, 5]

varทำให้เราล้มเหลวเนื่องจากการวนซ้ำทั้งหมดใช้iตัวแปรที่มีขอบเขตฟังก์ชันเดียวกันซึ่งมีค่า5หลังจากการวนซ้ำเสร็จสิ้น


6
เขาให้คำตอบเดียวกันกับที่ใช้ === แทนที่จะเป็น == หลังถูกทำลาย แต่คณะกรรมการมาตรฐาน ES ไม่ต้องการเปลี่ยนดังนั้นพวกเขาจึงเพิ่ม ===ไม่แน่ใจว่ามันหมายถึงอะไร ==ไม่หักเลย มันสามารถถูกกำหนดให้เป็นequality comparison using coersionCheck out github.com/getify/You-Dont-Know-JS/blob/master/
......

13
@AmmarCSE เป็นเอกสาร 39 หน้าที่ยอดเยี่ยมเกี่ยวกับการข่มขู่โดยนัย ใครบ้างที่สามารถระลึกถึงสิ่งต่างๆในขณะที่เขียนโปรแกรม Doug หมายถึง "แตก" ตามที่สรุปไว้ในstackoverflow.com/a/359509/1682419ในระยะสั้นและง่ายต่อการได้รับบิตเมื่อประเภทค่าแตกต่างจากที่เราสันนิษฐานไว้ คุณสามารถทำนายสิ่งเหล่านี้ทั้งหมดได้หรือไม่? [ '1.0' == 1.0, [1.0] == 1.0, [1.0] == '1.0', ['1.0'] == 1.0, [null] == '', [null] == 'null', '00' == false, [] == [], [] == 0, [] == '', [] == false, [] == true, [010] - [4] == ' 4.0 ', !![0], !![1], [0] == true, [1] == true, 1 == [[1]], 0 == [[0]], '1' == [1] ]
Jerry101

2
ขวาตัวอย่างส่วนใหญ่เกี่ยวข้องกับตัวถูกดำเนินการอาร์เรย์ มันเป็นเรื่องง่ายที่จะเข้าใจผลเมื่อคุณมองเข้าไปในtoStringและวิธีการของการดำเนินการสำหรับวัตถุ อย่างไรก็ตามถ้านั่นคือสิ่งที่มีความหมายโดยการแตกหักแล้วฉันก็เห็นว่ามันมาจากไหน :-)
AmmarCSE

3
ทำไมไม่ใช้ const ทุกครั้งที่ไม่สามารถแก้ไขได้ - เพียงแค่ถาม ผมหมายถึงทางเลือกที่จริงมันก็ไม่ได้อยู่ระหว่างletและvarแต่ระหว่างlet, varและconst
shabunc

4
varทำงานได้ตามที่ออกแบบไว้ แต่ไม่ใช่ว่าจะมีคนคาดหวังกี่คน มันเป็นข้อบกพร่องในการใช้งานไม่ใช่ข้อผิดพลาดในการใช้งาน
Jerry101

12

หากคุณเขียนรหัสที่ถูกต้องคุณอาจจะสามารถเปลี่ยนvarคำสั่งทั้งหมดเป็นletข้อความสั่งโดยไม่มีการเปลี่ยนแปลงทางความหมาย

letจะดีกว่าเพราะจะช่วยลดขอบเขตที่มองเห็นตัวระบุได้ มันช่วยให้เราสามารถประกาศตัวแปรได้อย่างปลอดภัยที่เว็บไซต์ของการใช้งานครั้งแรก

constletเป็นที่นิยม หากคุณไม่จำเป็นต้องกลายพันธุ์การอ้างอิงให้ใช้การconstประกาศ สิ่งนี้มีประโยชน์ทั้งหมดletพร้อมกับลดการปรากฏตัวของตัวแปรหน่วยและทำให้รหัสง่ายขึ้นโดยทั่วไปเกี่ยวกับเหตุผล หากคุณไม่แน่ใจว่าคุณจะต้องกลายพันธุ์ข้อมูลอ้างอิงหรือไม่ให้ประกาศconstจนกว่าคุณจะพบว่าคุณต้องการทำเช่นนั้น


5

ฉันไม่คิดว่าคุณผิด แต่มีข้อควรระวังในการใช้ var โดยพื้นฐานแล้วletควรจะช่วยให้นักพัฒนาสามารถหลีกเลี่ยงความโง่เขลาของ JavaScript ได้โดยเฉพาะอย่างยิ่งกับการตั้งชื่อที่ขัดแย้งกัน varดูเหมือนว่าจะมีขอบเขตที่ใหญ่กว่าเนื่องจากต้องการไปที่ขอบเขตฟังก์ชันปิด จะมีบางครั้งที่คุณต้องการ var เช่นเมื่อคุณต้องการตัวแปร temp เพื่อให้สามารถใช้งานได้ภายในขอบเขตของบล็อกภายในฟังก์ชั่นมิฉะนั้นการเลือกletvar จะช่วยให้นักพัฒนาที่มีข้อขัดแย้งในการตั้งชื่อ เมื่อทราบเบามันเป็นเรื่องของเวลานั้น ES6 letแนะนำ


3
อุณหภูมิvarในบล็อกมีอยู่ในฟังก์ชั่นทั้งหมดไม่ใช่แบบบล็อก มันเป็นคุณสมบัติที่ทำให้เข้าใจผิด
Jerry101

1

ฉันมักจะเห็นด้วยว่าควรใช้ "ปล่อย" ใน es6 เท่านั้น AFIK การประกาศ "ให้" สร้างข้อผิดพลาดอีกครั้ง (ซึ่งดี) ในขณะที่ด้วย "var" คุณเพียงแค่แทนที่ค่า (แม้ว่า "โหมดเข้มงวด" ใน es5 จะดูแลเช่นกัน)


-4

letหมายถึง "ให้ตัวแปรเท่ากับ" มันคือการประกาศในคำอื่น ๆ การเริ่มต้นและการกำหนด

มันมีอยู่ในทางตรงกันข้ามกับconstที่แน่นอนหมายถึง "คงที่" - ซึ่งเป็นสิ่งที่ตรงกันข้ามของตัวแปร

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

Let เพิ่มความไม่สอดคล้องกันทางความหมายนี้ใน Javascript

ตามหลักเหตุผลคุณสามารถให้ค่าคงที่เท่ากันเช่นกันเนื่องจากงานของคำหลัก "ให้" คือการกำหนดหน่วยความจำ

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

ดังนั้นการแนะนำletในตำแหน่งที่ไม่ถูกต้อง เพื่อให้แน่ใจว่าเราจำได้ว่าคำศัพท์นี่เป็นความผิดพวกเขายังตัดสินใจเปลี่ยนขอบเขตศัพท์ของletvs varดังนั้นความไม่สอดคล้องกันจึงเป็นสิ่งสำคัญที่สุดในจิตใจของเราเมื่อทำการดีบั๊ก

กล่าวอีกนัยหนึ่งletมีอยู่เพราะคน (หมายถึงผู้ดูแลภาษา) คิดว่า Javascript นั้นสอดคล้องกันมากเกินไปทำให้เข้าใจว่ามันเป็นสำนวนและสำนวน

หมายเหตุด้านข้างvarใช้งานไม่ได้ในบล็อก "ลูกศร" หากคุณต้องการรักษาบล็อกดังกล่าวเป็นปิด (เพราะvarถูกนำมาใช้ก่อนที่จะรักษาบล็อกเป็นปิด) แต่letทำไม่ได้


6
-1: อวดรู้ไร้ประโยชน์และยึดหลักความคิดเห็นเป็นหลัก
Joel Mueller

fijiaaron ล้อเล่นกับพวกเราที่นี่
Jerry101

ฉันเห็นใจคุณที่คุณไม่ชอบรูปแบบคำศัพท์letเพราะมันขัดแย้งกับน้ำเสียงของคำหลักอื่น ๆ ในหมวดหมู่เดียวกันใน JavaScript สิ่งนี้ยังไม่ตอบคำถามและไม่ได้ตอบคำถามอย่างดี Downvoted
Aluan Haddad

3
letไม่ใช่แค่นักพัฒนาที่ต้องการความซับซ้อนมากขึ้น เป็นจริงที่เข้าใจได้ง่ายยิ่งขึ้นเพราะเมื่อคุณวนรอบและปิดทับ vars การปิดจะรักษาค่าสุดท้ายของ var แต่เมื่อคุณทำเช่นเดียวกันกับการอนุญาตการปิดแต่ละครั้งในลูปจะมีค่าเป็นของตัวเอง la ตัวอย่างโดย @ Jerry101 ด้านบน
TKoL
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.