Tôi nên sử dụng 'let' vs 'const' trong ES6 bao nhiêu?


214

Gần đây tôi đã viết rất nhiều mã ES6 cho io.js. Không có nhiều mã trong tự nhiên để học hỏi, vì vậy tôi cảm thấy như mình đang xác định các quy ước của riêng mình khi tôi đi.

Câu hỏi của tôi là về khi sử dụng constvs let.

Tôi đã áp dụng quy tắc này: Nếu có thể, hãy sử dụng const. Chỉ sử dụng letnếu bạn biết giá trị của nó cần thay đổi. (Bạn luôn có thể quay lại và thay đổi constthành a letnếu sau đó hóa ra bạn cần thay đổi giá trị của nó.)

Lý do chính cho quy tắc này là nó dễ dàng áp dụng nhất quán. Không có khu vực màu xám.

Vấn đề là, khi tôi áp dụng quy tắc này, trong thực tế 95% các tuyên bố của tôi là const. Và điều này có vẻ kỳ lạ với tôi. Tôi chỉ sử dụng letcho những thứ như itrong một forvòng lặp, hoặc đôi khi cho những thứ như tổng số Fibonacci tích lũy (không xuất hiện nhiều trong cuộc sống thực). Tôi đã rất ngạc nhiên về điều này - hóa ra 95% 'biến' trong mã ES5 của tôi cho đến nay là cho các giá trị không thay đổi. Nhưng nhìn thấy consttất cả các mã của tôi cảm thấy sai bằng cách nào đó.

Vì vậy, câu hỏi của tôi là: sử dụng constnhiều như vậy có ổn không? Tôi thực sự nên làm những việc như thế const foo = function () {...};nào?

Hoặc tôi nên dự trữ constcho những tình huống mà bạn khó mã hóa một chữ theo nghĩa đen ở đầu mô-đun - loại bạn làm trong mũ đầy đủ, như thế const MARGIN_WIDTH = 410;nào?


7
Tôi nghi ngờ rằng câu hỏi này chủ yếu dựa trên quan điểm và do đó có khả năng bị đóng, nhưng 2 xu của tôi: Sử dụng constnhiều như vậy là ổn .
jhominal

15
function foo() {...}tốt hơn<anything> foo = function() {...}
OrangeDog

12
@OrangeDog Tôi muốn xem giải thích của bạn cho điều đó, vì tôi đã kết luận chính xác điều ngược lại. Có một cảnh báo function foo() {...}có thể gây nhầm lẫn nhỏ khi gỡ lỗi, do cẩu. Ngoài ra, sự tồn tại của nó có nghĩa là chúng ta có hai cấu trúc làm cùng một việc nhưng một trong số chúng chỉ hoạt động trong một bối cảnh rất cụ thể. (Bạn có thể sử dụng một biểu hiện chức năng ở bất cứ đâu một biểu thức có thể tồn tại, nhưng bạn chỉ có thể sử dụng một tuyên bố chức năng ở cấp tuyên bố.) Nếu bạn thích ngắn gọn, vấn đề chỉ có thể là rằng cú pháp biểu hiện chức năng sử dụng toàn bộ từ function.
Keen

11
Dấu vết ngăn xếp có tên của chức năng thay vì anon. Tời kéo là tốt và cho phép bạn xác định các chức năng theo thứ tự tự nhiên, mà không phải lo lắng về việc foo không được xác định.
OrangeDog

1
Đó là những điểm tốt để có trong tâm trí, nhưng tôi chưa bị thuyết phục. Trình gỡ lỗi hiện đại thực hiện tốt việc chọn tên hiển thị phù hợp cho chức năng của bạn dựa trên biểu tượng bạn gán cho nó (nếu có - nếu không, bạn có thể sử dụng biểu thức hàm được đặt tên). Thứ tự tự nhiên của khai báo chức năng là rất chủ quan. Có thể hợp lý khi nghĩ rằng thứ tự tự nhiên là bắt đầu bằng cách xác định các mảnh cơ bản, và sau đó xác định các mảnh sử dụng chúng.
Keen

Câu trả lời:


183

Câu trả lời của tôi ở đây không cụ thể về javascript.

Theo nguyên tắc thông thường trong bất kỳ ngôn ngữ nào cho phép tôi làm như vậy theo cách bán dễ dàng, tôi sẽ nói luôn sử dụng const / Final / readonly / bất cứ thứ gì nó được gọi trong ngôn ngữ của bạn bất cứ khi nào có thể. Lý do rất đơn giản, lý do về mã dễ dàng hơn nhiều khi nó rõ ràng những gì có thể thay đổi và những gì không thể thay đổi. Và ngoài ra, bằng nhiều ngôn ngữ, bạn có thể nhận được hỗ trợ công cụ cho bạn biết rằng bạn đang làm gì đó sai khi bạn vô tình gán cho một biến mà bạn đã khai báo là const.

Quay trở lại và thay đổi một const thành cho phép là chết đơn giản. Và đi const theo mặc định làm cho bạn suy nghĩ hai lần trước khi làm như vậy. Và đây là trong nhiều trường hợp một điều tốt.

Có bao nhiêu lỗi bạn đã thấy rằng các biến liên quan thay đổi bất ngờ? Tôi đoán rất nhiều. Tôi biết rằng phần lớn các lỗi mà tôi thấy liên quan đến những thay đổi trạng thái bất ngờ. Bạn sẽ không thoát khỏi tất cả các lỗi này bằng cách sử dụng const, nhưng bạn sẽ thoát khỏi rất nhiều lỗi!

Ngoài ra, nhiều ngôn ngữ chức năng có các biến bất biến trong đó tất cả các biến được tạo theo mặc định. Nhìn vào Erlang chẳng hạn, hoặc F #. Mã hóa mà không có sự phân công hoạt động hoàn hảo trong các ngôn ngữ này và là một trong nhiều lý do tại sao mọi người yêu thích lập trình chức năng. Có rất nhiều điều để học hỏi từ các ngôn ngữ này về việc quản lý nhà nước để trở thành một lập trình viên tốt hơn.

Và tất cả bắt đầu với việc cực kỳ tự do với const! ;) Đó chỉ là hai nhân vật nữa để viết so với cho phép, vì vậy hãy tiếp tục và consttất cả mọi thứ!


45
constlà hai nhân vật nhiều hơn let...
OrangeDog

72
Nhưng 5 ký tự ít hơn bất biến.
Cerad

7
Điều này có vẻ giống như sử dụng valtrong Scala (khai báo một biến là bất biến) và chỉ sử dụng var(tương đương có thể thay đổi) khi chúng ta không thể sử dụng val. Nói cách khác, chúng tôi khai báo các biến là bất biến theo mặc định và chỉ đưa ra khả năng biến đổi khi chúng tôi thực sự cần nó (điều này có thể đơn giản là vì cách tiếp cận có thể thay đổi là sạch hơn).
Kat

7
Tôi đồng ý với câu trả lời này nhưng hãy nhớ rằng mọi thứ không quá rõ ràng khi làm việc với những thứ như vật thể hoặc mảng đơn giản vì các thuộc tính của chúng có thể thay đổi ngay cả khi chúng được định nghĩa bằng 'const'. Tôi đã nghĩ về 'const' hoạt động như object.freeze nhưng không phải vậy.
backdesk

2
@Cerad Ý của bạn là 4 ký tự ít hơn hay tôi đang bỏ lỡ một số trò đùa ở đây?
Mathias Bynens

57

Hãy cẩn thận, bởi vì constcác khóa đối tượng là có thể thay đổi.

Từ đây: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

khóa đối tượng không được bảo vệ

xem xét ví dụ này:

const colors = {red: "#f00"}; 
console.log(colors); // { "red": "#f00" }

colors.red = "#00f";
colors.green = "#0f0";
console.log(colors); // { "red": "#00f", "green": "#0f0" }

Điều tương tự cho mảng:

const numbers = [1, 2, 3];
console.log(numbers); // [ 1, 2, 3 ]

numbers.push(4);
console.log(numbers); // [ 1, 2, 3, 4 ]

Tôi đã không quyết định hoàn toàn bản thân mình, nhưng tôi đang xem xét sử dụng constcho tất cả các đối tượng không phải là mảng / không phải đối tượng và sử dụng letcho các đối tượng / mảng.


34
IMO đúng, nhưng được mong đợi - điều không đổi là tham chiếu đối tượng được gán cho của bạn const. colors = numberssẽ không làm việc, như mong đợi. Nếu bạn muốn bảo vệ các thuộc tính đối tượng của mình, bạn có thể sử dụng Object.freeze() developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
Kẻ

16
Gây hiểu lầm. Nó là không thể thay đổi. Nhưng các thuộc tính đối tượng thực tế thì không.
Gaston Sanchez

1
+1 Vâng, tài liệu tham khảo được bảo vệ, nhưng về mặt câu hỏi , sẽ khá ngớ ngẩn khi sử dụng trong các trường hợp như const moment = require('moment'), trừ khi bạn là kiểu người lo lắng rằng ai đó sẽ cố gắng làm moment = dead.fish(() => pizza)sau.
MaxWell

5
Có lẽ thực tế hơn để lo lắng về moment = Date.now(). Nhưng trong mọi trường hợp, nếu mã giả định bất biến, tôi thấy không có gì sai khi thực thi nó khi có thể.
James M.

3
Không ai nói họ không bất biến, mặc dù. Đó là một sự hiểu lầm phổ biến rằng mục tiêu của const là làm cho nó trở nên bất biến, khi nó thực sự đảm bảo rằng cái tên sẽ không bao giờ nhắc đến một đối tượng khác với đối tượng mà nó được khởi tạo.
đơn sắc

25

Đừng lo lắng về nó. constlà một bổ sung tuyệt vời cho JavaScript và tôi khuyên bạn nên sử dụng tất cả những nơi có ý nghĩa. Nó làm cho mã mạnh mẽ hơn.

Khi nói đến các đối tượng, constsẽ bảo vệ biến của bạn khỏi việc gán lại, nhưng nếu bạn cần các đối tượng bất biến, bạn sẽ cần Object.freezephương thức, xem bên dưới.

const immutableOject = Object.freeze({immutableProperty: 'foo'});

constsẽ chỉ bảo vệ khỏi việc gán lại và freezephương pháp sẽ bảo vệ tất cả các thuộc tính ngay lập tức. Nếu bạn cần tất cả các thuộc tính lồng nhau là bất biến, thì bạn sẽ cần đệ quy freezechúng.


14
Lưu ý Object.freezelà nông.
Mathias Bynens

@MathiasBynens Tôi đã xem qua nhận xét này và tôi tò mò không biết chính xác ý của bạn là gì. Bạn có thể vui lòng giải thích?
Cole Roberts

@ColeRoberts Khái niệm về tính bất biến nông, là khi bản thân tham chiếu đối tượng là bất biến, nhưng các thuộc tính vẫn có thể được thay đổi. Từ khóa const chỉ tạo ra tính bất biến nông, do đó bạn cần sử dụng Object.freeze nếu tất cả các thuộc tính cũng không thay đổi.
Clean_coding

3
@ColeRoberts Có nghĩa là các giá trị đối tượng trong một đối tượng đóng băng (tức là các đối tượng lồng nhau) vẫn có thể bị thay đổi. Xem mathiasbynens.be/notes/es6-const#immutable-values để biết thêm thông tin.
Mathias Bynens

19

Trong ES6const của tôi không phải là về bài viết bất biến , tôi giải thích constchính xác những gì có nghĩa là theo thông số kỹ thuật.

Dựa trên những sự thật khách quan đó, đây là sở thích cá nhân của tôi:

[ V ]] thật hợp lý khi sử dụng letconstnhư sau trong mã ES6 của bạn:

  • sử dụng consttheo mặc định
  • chỉ sử dụng letnếu rebinding (tức là bất kỳ hình thức tái chỉ định nào) là cần thiết
  • ( varkhông nên được sử dụng trong ES6)

Chủ quan vì nó có thể, thực tế là điều này phù hợp nhất với ý định của thông số kỹ thuật.

Những người sử dụng lettheo mặc định thường coi constcác biến là hằng số (mà chúng không nhất thiết phải theo thiết kế!). Đối với mỗi người của họ, nhưng tôi thích sử dụng mọi thứ cho mục đích dự định của họ, và không phải vì một số ý nghĩa giả tạo mà mọi người gán cho nó dựa trên sự hiểu lầm.

constChỉ sử dụng cho các hằng số cũng giống như chỉ sử dụng phần tử HTML<aside> cho nội dung thanh bên.


2
Tại sao bạn sẽ đặt tên một cái gì đó constnếu nó không phải là hằng số?
nu everest

3
@nueverest Vì đó không phải constlà những gì dành cho. Bạn đã đọc những điều trên?
Mathias Bynens

2
@MathiasBynens Tôi nghĩ vấn đề (chỉ?) Với constnó được gọi là const. Đó là một cái tên ngớ ngẩn (trong javascript) lúc đầu làm cho nhiều nhà phát triển (tất cả?) Bối rối. IMO sẽ tốt hơn nếu constđược gọi let(đặc biệt là vì letngắn hơn nhưng constphổ biến hơn nhiều) và letđược gọi là thứ khác.
MrN00b

@MathiasBynens Tôi hiểu nhưng tại sao lại gọi như vậy? Nó đang tạo ra một lượng lớn nhầm lẫn như trang này chứng minh.
jtr13

4

Cách tiếp cận cá nhân của tôi, đã nghĩ để giúp đọc và hiểu mã:


letchỉ dành cho các biến có thời gian tồn tại ngắn, được xác định tại một dòng duy nhất và không thay đổi sau đó. Nói chung những biến đó là chỉ để giảm số lượng gõ. Ví dụ:

for (let key in something) {
  /* we could use `something[key]` for this entire block,
     but it would be too much letters and not good for the
     fingers or the eyes, so we use a radically temporary variable
  */
  let value = something[key]
  ...
}

constcho tất cả các tên được biết là không đổi trên toàn bộ mô-đun. Không bao gồm các giá trị không đổi cục bộ. Các valuetrong ví dụ trên, ví dụ, là hằng số trong phạm vi của nó và có thể được khai báo với const, nhưng vì có nhiều lần lặp và cho mỗi người có một giá trị với cùng một tên , "giá trị", mà có thể đánh lừa người đọc vào suy nghĩ valueluôn luôn là giống nhau. Các mô-đun và chức năng là ví dụ tốt nhất về constcác biến:

const PouchDB = require('pouchdb')
const instantiateDB = function () {}
const codes = {
  23: 'atc',
  43: 'qwx',
  77: 'oxi'
}

varcho tất cả mọi thứ có thể hoặc không thể thay đổi. Các tên có thể gây nhầm lẫn cho những người đọc mã, ngay cả khi chúng không đổi cục bộ và không phù hợp với let(nghĩa là chúng không được hoàn thành trong một khai báo trực tiếp đơn giản) áp dụng cho việc khai báo var. Ví dụ:

var output = '\n'
lines.forEach(line => {
  output += '  '
  output += line.trim()
  output += '\n'
})
output += '\n---'

for (let parent in parents) {
  var definitions = {}
  definitions.name = getName(parent)
  definitions.config = {}
  definitions.parent = parent
}

Bình luận thêm và có thể cập nhật trong tương lai ở đây .


10
đoạn mã thứ hai đó trông giống như một khẩu súng.
Julian

1

JavaScript hơi đặc biệt ở chỗ các biến có thể là các hàm và như vậy, nhưng hãy xem xét trong C #, Java hoặc ngôn ngữ kiểu C tương tự khác:

const public void DoSomething()

Điều constnày thật kỳ quặc và đó là bởi vì các khai báo phương thức trong các ngôn ngữ này không thể thay đổi, một khi chúng được biên dịch thành một thứ khác, đó là những gì chúng làm, bất kể là gì (bỏ qua một số hack khủng khiếp có thể tồn tại).

Tại sao JavaScript phải khác nhau? Vì vậy, nó không được biên dịch, nhưng điều đó không có nghĩa là chúng ta nên loại bỏ sự an toàn mà trình biên dịch có thể cung cấp. Sử dụng consttừ khóa mang lại cho chúng ta sự an toàn hơn, điều này chắc chắn sẽ dẫn đến các ứng dụng mạnh mẽ hơn.

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.