Sử dụng đúng const để xác định các hàm trong JavaScript


183

Tôi quan tâm nếu có bất kỳ giới hạn nào đối với loại giá trị nào có thể được đặt bằng constJavaScript trong các hàm cụ thể. Điều này có hợp lệ không? Cấp cho nó không hoạt động, nhưng nó được coi là thực hành xấu vì lý do nào?

const doSomething = () => {
   ...
}

Tất cả các chức năng nên được định nghĩa theo cách này trong ES6? Có vẻ như điều này không xảy ra, nếu vậy.

Cảm ơn cho bất kỳ ý kiến!


Bạn dường như đặt nhiều câu hỏi: 1) "Tôi quan tâm nếu có bất kỳ giới hạn nào đối với loại giá trị nào có thể được đặt bằng const trong JavaScript" Số 2) "Điều này có hợp lệ không?" Đúng. 3) "nó được coi là thực hành tồi vì bất kỳ lý do gì" Tôi đoán nó đã không tồn tại đủ lâu để nói bất cứ điều gì về điều đó nhưng tôi không hiểu tại sao đây nên là thực hành pad. Nó không khác nhiều lắm var doSomething = <function def>;. 4) "Có nên xác định tất cả các chức năng theo cách này trong ES6 không?" Có vẻ rườm rà với tôi. Tôi thích khai báo hàm. Mọi người đều là của riêng họ.
Felix Kling

1
Cách tôi nhìn thấy nó (ý kiến, không phải là một thực tế), nó có ý nghĩa nếu bạn muốn không cho phép xác định lại các chức năng. Cho dù đó là lành mạnh, hoặc liệu nó có sử dụng chức năng - điều đó gây tranh cãi. Nếu bạn nghĩ rằng nó phù hợp với kịch bản sử dụng của bạn, tôi không nghĩ ai đó có thể tranh luận về quyết định của bạn và cho rằng đó là thông lệ xấu.
Mjh

4
Tôi đoán câu hỏi là những gì bạn muốn đạt được với const. Bạn có muốn ngăn mình vượt qua chức năng không? Tôi giả sử bạn biết mã của mình để không làm điều này. Bạn có muốn thể hiện ý định của nó doSomething, tức là nó giữ một chức năng và không thay đổi giá trị của nó? Tôi nghĩ rằng khai báo chức năng truyền đạt ý định này là rõ ràng là tốt. Vì vậy, nếu bạn cần "bảo vệ thời gian chạy" khỏi ghi đè, hãy truy cập nó. Nếu không, tôi không thấy nhiều lợi ích. Tất nhiên nếu bạn chủ yếu sử dụng để sử dụng var foo = function() {};, tôi sẽ sử dụng constthay vì var.
Felix Kling

5
@FelixKling, "Tôi cho rằng bạn biết mã của mình để không làm điều này." - đây là tranh luận khá tệ. Mặt khác, không có ý nghĩa gì constcả.
meandre

Câu trả lời:


253

Không có vấn đề gì với những gì bạn đã làm, nhưng bạn phải nhớ sự khác biệt giữa khai báo hàm và biểu thức hàm.

Một khai báo hàm, đó là:

function doSomething () {}

Được nâng lên hoàn toàn đến đỉnh của phạm vi (và thích letconstchúng cũng nằm trong phạm vi khối).

Điều này có nghĩa là những điều sau đây sẽ hoạt động:

doSomething() // works!
function doSomething() {}

Một biểu thức hàm, đó là:

[const | let | var] = function () {} (or () =>

Là việc tạo ra một chức năng ẩn danh (function () {} ) và tạo ra một biến, và sau đó gán hàm ẩn danh đó cho biến đó.

Vì vậy, các quy tắc thông thường xung quanh việc nâng biến trong phạm vi - các biến trong phạm vi khối ( letconst) không được nâng undefinedlên trên đỉnh của phạm vi khối của chúng.

Điều này có nghĩa là:

if (true) {
    doSomething() // will fail
    const doSomething = function () {}
}

Sẽ thất bại vì doSomethingkhông được xác định. (Nó sẽ ném một ReferenceError)

Nếu bạn chuyển sang sử dụng, varbạn sẽ nhận được biến của mình, nhưng nó sẽ được khởi tạo để undefinedkhối mã ở trên vẫn không hoạt động. (Điều này sẽ ném TypeErrordoSomethingkhông phải là một chức năng tại thời điểm bạn gọi nó)

Theo như thông lệ tiêu chuẩn, bạn nên luôn luôn sử dụng công cụ thích hợp cho công việc.

Axel Rauschmayer có một bài viết tuyệt vời về phạm vi và cẩu bao gồm ngữ nghĩa es6: Biến và phạm vi trong ES6


7
Chỉ muốn thêm rằng các lớp es6 sử dụng const bên trong để bảo vệ tên lớp khỏi bị gán lại trong lớp.
dùng2342460

2
Một sự khác biệt tinh tế giữa a function a(){console.log(this);}b const a=_=>{console.log(this);} là nếu bạn gọi nó như thế nào a.call(someVar);, trong a , nó sẽ in someVar, trong b , nó sẽ in window.
Qian Chen

100

Mặc dù sử dụng constđể xác định các chức năng có vẻ như là một hack, nhưng nó đi kèm với một số lợi thế lớn làm cho nó vượt trội (theo ý kiến ​​của tôi)

  1. Nó làm cho hàm không thay đổi, vì vậy bạn không phải lo lắng về chức năng đó bị thay đổi bởi một số đoạn mã khác.

  2. Bạn có thể sử dụng cú pháp mũi tên chất béo, ngắn hơn và sạch hơn.

  3. Sử dụng các chức năng mũi tên sẽ chăm sóc thisràng buộc cho bạn.

ví dụ với function

// define a function
function add(x, y) { return x + y; }

// use it
console.log(add(1, 2)); // 3

// oops, someone mutated your function
add = function (x, y) { return x - y; };

// now this is not what you expected
console.log(add(1, 2)); // -1

cùng ví dụ với const

// define a function (wow! that is 8 chars shorter)
const add = (x, y) => x + y;

// use it
console.log(add(1, 2)); // 3

// someone tries to mutate the function
add = (x, y) => x - y; // Uncaught TypeError: Assignment to constant variable.
// the intruder fails and your function remains unchanged


1
Và bạn có thể hai lần khai báo hàm add (x, y), nhưng bạn không thể khai báo hai lần const add = ...
TatianaP

33
1. Tính bất biến là một lợi ích thực sự, nhưng rất hiếm khi ai đó thực sự ghi đè lên một chức năng. 2. Cú pháp mũi tên béo không ngắn hơn trừ khi chức năng của bạn có thể là một biểu thức. function f(x, y) {là 18 ký tự, const f = (x, y) => {là 21 ký tự, vì vậy dài hơn 3 ký tự. 3. Giữ ràng buộc này chỉ quan trọng nếu các hàm được xác định bên trong một phương thức (hoặc hàm khác có ý nghĩa này). Ở kịch bản cấp cao nhất là vô nghĩa. Tôi không nói bạn sai, chỉ là những lý do bạn đề cập không liên quan lắm.
Khỏa thân

@Nakenible vậy một số lý do hợp lệ khác là gì?
Anish Ramaswamy

13
Một lợi thế của cú pháp hàm lỗi thời là trong quá trình gỡ lỗi, nó có tên.
dùng949300

3
Tôi sẽ sử dụng linters để ngăn chặn ràng buộc lại khai báo hàm.
Franklin Yu

32

Đã ba năm kể từ khi câu hỏi này được hỏi, nhưng tôi mới bắt gặp nó. Vì câu trả lời này nằm quá xa ngăn xếp, xin vui lòng cho phép tôi lặp lại nó:

H: Tôi quan tâm nếu có bất kỳ giới hạn nào đối với loại giá trị nào có thể được đặt bằng cách sử dụng const trong JavaScript. Điều này có hợp lệ không? Cấp cho nó không hoạt động, nhưng nó được coi là thực hành xấu vì lý do nào?

Tôi đã có động lực để thực hiện một số nghiên cứu sau khi quan sát một bộ mã hóa JavaScript phổ biến, người luôn sử dụng constcâu lệnh functions, ngay cả khi không có lý do / lợi ích rõ ràng.

Để trả lời cho " nó có bị coi là thực hành xấu vì bất kỳ lý do gì không? " Hãy để tôi nói, IMO, đúng vậy, hoặc ít nhất, có những lợi thế khi sử dụng functiontuyên bố.

Dường như với tôi rằng đây phần lớn là vấn đề sở thích và phong cách. Có một số đối số tốt được trình bày ở trên, nhưng không có gì rõ ràng như được thực hiện trong bài viết này:

Sự nhầm lẫn liên tục: tại sao tôi vẫn sử dụng các câu lệnh hàm JavaScript của Medium.freecodecamp.org/Bill Sourour, JavaScript guru, nhà tư vấn và giáo viên.

Tôi kêu gọi mọi người đọc bài báo đó, ngay cả khi bạn đã đưa ra quyết định.

Đây là những điểm chính:

Các câu lệnh hàm có hai ưu điểm rõ ràng so với biểu thức hàm [const]:

Ưu điểm số 1: Sự rõ ràng của ý định

Khi quét qua hàng ngàn dòng mã mỗi ngày, thật hữu ích để có thể tìm ra ý định của lập trình viên nhanh chóng và dễ dàng nhất có thể.

Ưu điểm số 2: Thứ tự khai báo == thứ tự thực hiện

Lý tưởng nhất, tôi muốn khai báo mã của mình ít nhiều theo thứ tự mà tôi mong đợi nó sẽ được thực thi.

Đây là showstopper cho tôi: mọi giá trị được khai báo sử dụng từ khóa const đều không thể truy cập được cho đến khi thực thi đạt đến nó.

Những gì tôi vừa mô tả ở trên buộc chúng ta phải viết mã trông lộn ngược. Chúng ta phải bắt đầu với chức năng cấp thấp nhất và làm việc theo cách của chúng tôi.

Bộ não của tôi không hoạt động theo cách đó. Tôi muốn bối cảnh trước các chi tiết.

Hầu hết các mã được viết bởi con người. Vì vậy, điều hợp lý là hầu hết trật tự hiểu biết của mọi người gần như tuân theo thứ tự thực thi của hầu hết các mã.


1
Bạn có thể bình luận thêm một chút về sự rõ ràng của ý định? Tôi nhận được # 2, nhưng theo như tôi có thể nói # 1 chỉ là một sự lặp lại (trước?) Của # 2. Tôi có thể nghĩ về một trường hợp, tức là các hàm có defaultErrorHandlerconst riêng được gán là hàm ẩn danh mà sau đó tôi có thể gọi từ các trình xử lý lời hứa. Điều này sẽ cho phép tôi tùy ý 'ghi đè' trình xử lý lỗi mặc định này trong các chức năng mà tôi cần. Một số chỉ cần trả về một đối tượng lỗi và những người khác cần trả về một phản hồi http, mức độ chi tiết khác nhau. Tuy nhiên, cấu trúc mã có thể là một mẫu quen thuộc bất kể.
Jake T.

Có lẽ ý tưởng của tôi là quá phức tạp mặc dù! Chỉ cần quấn đầu xung quanh một số thực hành mới, chưa dành nhiều thời gian để thực hiện chúng. Chỉ cần tìm thấy tôi thực sự thích .then( res.success, res.error )nhiều hơn các chức năng ẩn danh mà tôi đã tuyên bố chỉ gọi res.success(value);. Có một .then( ..., defaultErrorHandler)mẫu chung có thể là tốt, với hàm defaultErrorHandler được xác định ở mức cao nhất và tùy ý có một const defaultErrorHandler = error => { ... }khai báo trong phạm vi hàm như mong muốn.
Jake T.

1
@JakeT. RE "Bạn có thể bình luận thêm một chút về sự rõ ràng của ý định?". Chà, trước hết, câu nói đó không phải là của tôi, mà bởi freecodecamp.org/Bill Sourour, tác giả của bài báo đó. Nhưng nó thực sự có ý nghĩa chung với tôi. Nếu tôi đọc "hàm ngày mai ()" thì tôi biết ngay đó là hàm. Nhưng nếu tôi đọc "const ngày mai = () =>", tôi đã dừng lại một chút và phân tích cú pháp trong đầu để cuối cùng xác định, OK, yeah, đó là một chức năng.
JMichaelTX

1
Một điều nữa, nếu tôi có một đoạn script dài được viết bởi người khác và tôi muốn xem tất cả các chức năng, tôi có thể thực hiện tìm kiếm nhanh trên "hàm" để tìm chúng. Hoặc thậm chí tốt hơn, tôi có thể viết một JS RegEx nhanh để trích xuất tất cả các hàm. IMO, câu lệnh "const" chỉ dành cho dữ liệu (không phải chức năng) sẽ KHÔNG thay đổi.
JMichaelTX

10

Có một số lợi ích rất quan trọng đối với việc sử dụng constvà một số người sẽ nói rằng nó nên được sử dụng bất cứ khi nào có thể vì nó có chủ ý và chỉ định như thế nào.

Đó là, theo như tôi có thể nói, việc khai báo các biến số có thể dự đoán và có thể dự đoán nhất trong JavaScript và là một trong những điều hữu ích nhất, BECAUSE về mức độ hạn chế của nó. Tại sao? Bởi vì nó loại bỏ một số khả năng có sẵn varletkhai báo.

Những gì bạn có thể suy luận khi bạn đọc một const? Bạn biết tất cả những điều sau đây chỉ bằng cách đọcconst câu lệnh khai báo, mà không cần quét các tham chiếu khác đến biến đó:

  • giá trị được liên kết với biến đó (mặc dù đối tượng cơ bản của nó không phải là bất biến sâu sắc)
  • nó không thể được truy cập bên ngoài khối chứa ngay lập tức của nó
  • ràng buộc không bao giờ được truy cập trước khi khai báo, vì các quy tắc Khu vực chết tạm thời (TDZ).

Các trích dẫn sau đây là từ một bài viết lập luận về lợi ích của letconst. Nó cũng trực tiếp trả lời câu hỏi của bạn về các hạn chế / giới hạn của từ khóa:

Các ràng buộc như được cung cấp bởi letconstlà một cách mạnh mẽ để làm cho mã dễ hiểu hơn. Cố gắng tích lũy càng nhiều các ràng buộc này càng tốt trong mã bạn viết. Càng nhiều ràng buộc khai báo làm hạn chế ý nghĩa của một đoạn mã, con người càng dễ đọc và nhanh hơn để đọc, phân tích và hiểu một đoạn mã trong tương lai.

Cấp, có nhiều quy tắc cho một consttuyên bố hơn là một vartuyên bố: phạm vi khối, TDZ, gán tại khai báo, không phân công lại. Trong khi đó varchỉ báo cáo phạm vi chức năng tín hiệu. Tuy nhiên, việc đếm quy tắc không cung cấp nhiều thông tin chuyên sâu. Tốt hơn là cân nhắc các quy tắc này về độ phức tạp: quy tắc này có thêm hoặc bớt độ phức tạp không? Trong trường hợpconst , phạm vi khối có nghĩa là phạm vi hẹp hơn phạm vi chức năng, TDZ có nghĩa là chúng ta không cần quét phạm vi ngược từ khai báo để phát hiện việc sử dụng trước khi khai báo và quy tắc gán có nghĩa là ràng buộc sẽ luôn bảo toàn cùng tham khảo.

Các câu lệnh bị ràng buộc càng nhiều, một đoạn mã càng đơn giản. Khi chúng ta thêm các ràng buộc cho ý nghĩa của một câu lệnh, mã trở nên ít khó đoán hơn. Đây là một trong những lý do lớn nhất tại sao các chương trình gõ tĩnh thường dễ đọc hơn các chương trình gõ động. Gõ tĩnh đặt một ràng buộc lớn đối với người viết chương trình, nhưng nó cũng đặt ra một ràng buộc lớn về cách chương trình có thể được diễn giải, làm cho mã của nó dễ hiểu hơn.

Với những lý lẽ này, bạn nên sử dụng constkhi có thể, vì đó là tuyên bố mang lại cho chúng ta ít khả năng suy nghĩ nhất.

Nguồn: https://ponyfoo.com/articles/var-let-const

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.