Có bất kỳ lý do để sử dụng từ khóa var var trong ES6 không?


261

Hướng dẫn của Babel về ES6 nói:

letlà mới var.

Rõ ràng sự khác biệt duy nhất là varđược phân chia theo chức năng hiện tại , trong khi letđược phân chia theo khối hiện tại . Có một số ví dụ tốt trong câu trả lời này .

Tôi không thể thấy bất kỳ lý do để sử dụng vartrong mã ES6. Ngay cả khi bạn muốn phạm vi một biến đã cho cho toàn bộ hàm, bạn vẫn có thể làm như vậy bằng letcách đặt khai báo ở đầu khối chức năng, đây là điều bạn nên làm với vardù sao để chỉ ra phạm vi thực tế. Và nếu bạn muốn phạm vi một cái gì đó tốt hơn trong một forkhối hoặc một cái gì đó, thì bạn cũng có thể làm điều đó.

Vì vậy, bản năng của tôi là ngừng sử dụng varhoàn toàn khi viết mã ES6.

Câu hỏi của tôi là, tôi có sai về điều này? Có trường hợp hợp pháp nào varthích hợp hơn letkhông?


3
Tôi chưa thử điều này (vì tôi chưa viết mã ES6), nhưng dường như việc sử dụng varnhư một chỉ báo có ý thức rằng biến này được dự định nằm trong toàn bộ chức năng có thể là một quy ước "tự ghi lại tài liệu" hữu ích .
jfriend00

10
Nếu bạn đặt một letcâu lệnh ngay trên đầu của một hàm, tôi nghĩ rõ ràng là bạn có ý định phạm vi nó cho toàn bộ hàm. Tôi không nghĩ việc sử dụng varlàm cho nó rõ ràng hơn là chỉ đơn giản là đặt nó ở trên cùng.
callum

11
Thành thật mà nói, tôi tin rằng lý do duy nhất varvẫn còn tồn tại, là khả năng tương thích ngược. Nếu không phải như vậy, họ đã loại bỏ varhoàn toàn, hoặc không bao giờ được giới thiệu letở nơi đầu tiên, thay vào đó thay đổi ngữ nghĩa của varnhững gì được cho là nên có.
Jörg W Mittag

2
@RayToal Tôi đồng ý với 97% những gì Kyle Simpson nói, nhưng lý do của anh ta để sử dụng varcó vẻ mỏng đối với tôi, và không đủ để đảm bảo có một loại biến thứ ba nhảy xung quanh. Bạn có thể phạm vi một lettoàn bộ chức năng chỉ bằng cách đặt nó ở trên cùng của chức năng, điều này rõ ràng hơn nhiều so với việc viết vartrong một khối (để đưa nó ra khỏi khối đó để bạn có thể sử dụng nó bên ngoài khối đó - kỳ dị). Ông cảnh báo rằng nếu bạn phạm vi một letchức năng thì "đó chỉ là vị trí báo hiệu sự khác biệt, chứ không phải cú pháp", nhưng tôi nghĩ đó là một điều tốt.
Callum

2
@RayToal Tôi cũng đã đọc bài viết đó (ngay trước khi đọc cuộc thảo luận này) và tôi thực sự thất vọng vì trường hợp rất yếu của anh ấy var. các ví dụ anh trình bày để giữ vardường như bị chiếm đoạt - và dựa trên các lỗi mã hóa nghiêm trọng . Sẽ tốt hơn nhiều khi gặp phải một lỗi và buộc phải sửa các lỗi đó hơn là sử dụng các chức năng ngôn ngữ để cho phép một người thoát khỏi nó! Điều gì tiếp theo, khuyên nên bọc mọi thứ trong một lần thử / bắt để tránh sự cố? Phần còn lại của liên kết đó là tốt nhưng tôi không đồng ý với phần cụ thể đó.
Mörre

Câu trả lời:


217

Doug Crockford thảo luận lettại thời điểm này trong bài nói chuyện của mình, " Các bộ phận tốt hơn ".

Vấn đề là, lettránh một nguồn hiểu lầm, đặc biệt. cho các lập trình viên với những kỳ vọng được đặt bởi các ngôn ngữ có phạm vi khối. A varphạm vi chức năng (nó khai báo một biến có thể nhìn thấy trong toàn bộ hàm) mặc dù có vẻ như nó có phạm vi khối .

var có thể vẫn có thể hữu ích trong trường hợp cực đoan như mã do máy tạo ra, nhưng tôi đang cố gắng hết sức ở đó.

( constcũng mới và có phạm vi chặn. Sau khi let x = {'hi': 'SE'}bạn có thể gán lại x, trong khi sau khi const y = xbạn không thể gán lại y. Điều đó thường thích hơn vì nó giữ thứ gì đó vô tình thay đổi từ bên dưới bạn. Nhưng rõ ràng, bạn vẫn có thể sửa đổi đối tượng y.hi = 'SO'trừ khi bạn Đóng băng nó.)

Trên thực tế, ấn tượng của bạn là đúng với ES6: Thông qua letconst. Ngừng sử dụng var.

(Trong một màn trình diễn khác của "The Better Parts" , Doug nói tại sao ===được thêm vào thay vì khắc phục các vấn đề của== . Tạo ==ra một số kết quả "đáng ngạc nhiên", vì vậy chỉ cần áp dụng ===.)


Một ví dụ tiết lộ

Mozilla Developer Network đưa ra một ví dụ varkhông hoạt động như dự định. Ví dụ của họ là một ví dụ thực tế đặt onclicktrình xử lý trong một trang web. Đây là một trường hợp thử nghiệm nhỏ hơn:

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]

varkhông thành công vì tất cả các lần lặp lặp đều có chung ibiến phạm vi hàm, có giá trị 5sau khi vòng lặp kết thúc.


6
Anh ta đưa ra câu trả lời tương tự về việc áp dụng === thay vì ==. Cái sau bị hỏng nhưng ủy ban tiêu chuẩn ES không muốn thay đổi nó, vì vậy họ đã thêm === Không hoàn toàn chắc chắn điều đó có nghĩa là gì. ==hoàn toàn không bị phá vỡ Nó có thể được định nghĩa đơn giản là equality comparison using coersionKiểm tra github.com/getify/You-Dont-Know-JS/blob/master/ chủ
AmmarCSE

13
@AmmarCSE đó là một tài liệu 39 trang tuyệt vời về các ép buộc ngầm. Ai có thể giữ tất cả những điều đó trong tâm trí khi lập trình? Doug có nghĩa là "bị hỏng" như được tóm tắt trong stackoverflow.com/a/359509/1682419 , nói ngắn gọn, dễ dàng để có được bit khi các loại giá trị thay đổi nhiều hơn chúng ta đoán. Bạn có thể dự đoán tất cả những điều này? [ '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
đúng, hầu hết các ví dụ liên quan đến một toán hạng mảng. Thật dễ hiểu kết quả khi bạn xem xét toString và cách nó được triển khai cho các Đối tượng . Tuy nhiên, nếu đó là những gì có nghĩa là bị phá vỡ thì tôi hoàn toàn thấy điều đó đến từ đâu. :-)
AmmarCSE

3
Tại sao không sử dụng const bất cứ khi nào nó không thể thay đổi - chỉ cần hỏi? Ý tôi là, sự lựa chọn thực sự không phải giữa letvarmà là giữa let, varconst
shabunc

4
varHoạt động như thiết kế, nhưng không phải là bao nhiêu người mong đợi. Đó là một lỗi sử dụng, không phải là lỗi thực hiện.
Jerry101

12

Nếu bạn đã viết mã chính xác, có lẽ bạn sẽ có thể biến tất cả các varcâu lệnh thành letcâu lệnh mà không có bất kỳ thay đổi ngữ nghĩa nào.

letđược ưa thích hơn vì nó làm giảm phạm vi mà định danh hiển thị. Nó cho phép chúng ta khai báo các biến một cách an toàn tại trang web của lần sử dụng đầu tiên.

constlà một lợi thế để let. Trừ khi bạn cần thay đổi một tài liệu tham khảo, hãy sử dụng một constkhai báo. Điều này có tất cả các lợi ích letcùng với việc giảm sự hiện diện của các biến đơn vị hóa và làm cho mã nói chung dễ dàng hơn để lý do. Nếu bạn không chắc chắn liệu mình có cần phải thay đổi một tài liệu tham khảo hay không, hãy khai báo constcho đến khi bạn thấy mình cần phải làm điều đó một cách rõ ràng.


5

Tôi không nhất thiết nghĩ rằng bạn sai nhưng có một số lưu ý khi sử dụng var. Về cơ bản, letsẽ giúp các nhà phát triển khắc phục sự ngu ngốc của JavaScript, đặc biệt là với các xung đột đặt tên. var, có vẻ như, có phạm vi lớn hơn vì nó muốn đi đến phạm vi chức năng đóng. Sẽ có lúc bạn cần var, như khi bạn cần một biến tạm thời có sẵn trong phạm vi của một khối bên trong hàm, nếu không, việc thích lethơn var sẽ giúp các nhà phát triển đặt tên xung đột. Trên một ghi chú nhẹ hơn, đó là khoảng thời gian ES6 giới thiệu let.


3
Một temp vartrong một khối có sẵn bên trong toàn bộ chức năng, không có phạm vi khối. Đó là một tính năng sai lệch.
Jerry101

1

Tôi có xu hướng đồng ý rằng chỉ nên sử dụng "let" trong es6. AFIK, khai báo lại "cho phép" tạo ra một lỗi (điều này là tốt), trong khi với "var", bạn chỉ cần ghi đè giá trị (mặc dù "chế độ nghiêm ngặt" trong es5 cũng xử lý vấn đề đó).


-4

letcó nghĩa là "hãy để biến bằng". Nói cách khác, đó là một tuyên bố, khởi tạo và chuyển nhượng.

Nó tồn tại trái ngược với constđiều tất nhiên có nghĩa là "hằng số" - trái ngược với biến.

Một số ngôn ngữ khác sử dụng tiền tố cho đối tượng thực tế thay vì đối tượng khi khai báo nó (ví dụ: defviết tắt cho "hàm xác định" - hoàn toàn thiếu điểm của "def".

Let thêm sự không nhất quán ngữ nghĩa này vào Javascript.

Theo logic, bạn cũng có thể để một hằng số bằng nhau, vì công việc của từ khóa "cho phép" là gán bộ nhớ.

Vấn đề phát sinh do vartừ khóa đã được giới thiệu trước đó constđã được hỗ trợ, do đó khả năng tương thích ngược chỉ ra rằng varkhông cần thiết có nghĩa là một biến. (Nó cũng có thể được sử dụng để gán giá trị không đổi.)

Do đó, việc giới thiệu letở vị trí sai. Để chắc chắn rằng chúng tôi nhớ rằng từ vựng, điều này là sai, họ cũng quyết định thay đổi phạm vi từ vựng của letvs var, vì vậy sự không nhất quán là quan trọng nhất trong suy nghĩ của chúng tôi khi gỡ lỗi.

Nói cách khác, lettồn tại bởi vì mọi người (có nghĩa là những người duy trì ngôn ngữ) nghĩ rằng Javascript quá phù hợp, đã thành thạo tất cả các thành ngữ và thành ngữ, mong muốn nhiều hơn.

Lưu ý bên cạnh, varkhông hoạt động trong các khối "mũi tên" nếu bạn muốn coi các khối nói là đóng (vì varđã được giới thiệu trước khi coi các khối là đóng), nhưng letthực tế.


6
-1: phạm vi, không có ích, và chủ yếu dựa trên quan điểm.
Joel Mueller

fijiaaron chỉ đùa với chúng tôi ở đây.
Jerry101

Tôi đồng cảm với việc bạn không thích hình thức từ vựng letbởi vì nó không đồng nhất với âm của các từ khóa khác trong cùng thể loại trong JavaScript. Tuy nhiên, điều này không trả lời câu hỏi, và không đặc biệt tốt. Downvote
Aluan Haddad

3
letkhông chỉ là các nhà phát triển mong muốn phức tạp hơn. Nó thực sự dễ hiểu hơn, bởi vì khi bạn lặp và đóng trên các vars, bao đóng duy trì giá trị cuối cùng của var, nhưng khi bạn thực hiện tương tự cho phép, mỗi bao đóng trong vòng lặp có giá trị riêng cho phép, a la ví dụ của @ Jerry101 ở trên
TKoL
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.