JSLint Mong đợi '===' và thay vào đó thấy '=='


90

Gần đây, tôi đang chạy một số mã của mình thông qua JSLint thì gặp lỗi này. Điều tôi nghĩ là buồn cười về lỗi này mặc dù nó tự động giả định rằng tất cả == phải là ===.

Điều đó có thực sự có ý nghĩa không? Tôi có thể thấy rất nhiều trường hợp mà bạn không muốn so sánh loại và tôi lo lắng rằng điều này thực sự có thể gây ra vấn đề.

Từ "Dự kiến" sẽ ngụ ý rằng điều này nên được thực hiện MỌI lần ..... Đó là điều không có ý nghĩa đối với tôi.


7
Tôi cũng gặp phải vấn đề này với JSLint. Tôi đã thực hiện cập nhật từ == thành === và nó thực sự đã phá vỡ mã hoạt động trước đó.
kemiller2002

5
Nếu mã của bạn có hơn 100 dòng, nó sẽ không vượt qua jslint, thực sự là không thể.

3
"Broke" là một từ quá mạnh. Nó đã thay đổi ý nghĩa mã của bạn. Nếu bạn đang myVar == nullkiểm tra, có, những thay đổi lớn. ; ^) Lập luận của Crockford là nó làm cho ý nghĩa của mã chính xác hơn, và điều đó thật khó để tranh luận.
ruffin

Câu trả lời:


127

IMO, sử dụng một cách mù quáng ===, mà không cố gắng hiểu cách chuyển đổi kiểu hoạt động không có nhiều ý nghĩa.

Nỗi sợ hãi chính về toán tử Equals ==là các quy tắc so sánh tùy thuộc vào các kiểu được so sánh có thể làm cho toán tử không có tính bắc cầu, ví dụ, nếu:

A == B AND
B == C

Không thực sự đảm bảo rằng:

A == C

Ví dụ:

'0' == 0;   // true
 0  == '';  // true
'0' == '';  // false

Toán tử nghiêm ngặt bằng ===không thực sự cần thiết khi bạn so sánh các giá trị cùng loại, ví dụ phổ biến nhất:

if (typeof foo == "function") {
  //..
}

Chúng tôi so sánh kết quả của typeoftoán tử, luôn là một chuỗi , với một chuỗi tự ...

Hoặc khi bạn biết các quy tắc ép buộc loại, ví dụ, kiểm tra xem có điều gì đó nullhoặc undefinedmột cái gì đó:

if (foo == null) {
  // foo is null or undefined
}

// Vs. the following non-sense version:

if (foo === null || typeof foo === "undefined") {
  // foo is null or undefined
}

1
Tôi ghét quy tắc này của JSLint. Tôi nghĩ rằng vấn đề thực sự là mọi người không nên sử dụng các toán tử theo cách mà họ không hiểu (trớ trêu thay, những người này thường giống như những người sẽ thay thế một cách mù quáng '===' bằng '=='). Chắc chắn, có một vài trường hợp thông thường phát sinh khi so sánh số 0 với các chuỗi khác nhau, nhưng nếu bạn đang so sánh dữ liệu không liên quan như 0 == 'đây là một chuỗi' - Mã của bạn có thể gặp vấn đề lớn hơn gấp đôi bằng! Nếu bạn biết chắc chắn những loại bạn đang xử lý và bạn biết chính xác cách chúng tương tác với ==, thì tôi nghĩ bạn nên sử dụng nó.
Jon

3
@Jon Điểm của ===nhà điều hành là sự rõ ràng của mã. Không có tình huống hợp lý để sử dụng ==vì nó sẽ không bao giờ rõ ràng và dễ hiểu như toán tử nhận dạng. Vấn đề không phải là bạn có hiểu các toán tử hay không, mà là sử dụng toán tử giúp mã của bạn dễ đọc hơn mà hầu như không phải trả phí. Các nhà phát triển duy nhất đang tranh cãi chống lại nhà điều hành danh tính là các nhà phát triển đơn lẻ và những người không làm việc theo nhóm. Theo định nghĩa, những người mã không được xem xét bởi đủ con mắt.
Alternatex

2
Tôi thấy so sánh == null gần như là cần thiết. Vấn đề càng trở nên ít quan trọng hơn nếu mã của bạn được kiểm tra tốt.
Jon

1
Trong thực tế, có những lúc việc sử dụng == là cần thiết, để thực hiện kiểm tra bắt buộc. nếu foo.toString () sẽ hoạt động theo kiểu có thể dự đoán được và một chuỗi đơn giản cần được kiểm tra đối với đầu ra đó thì việc viết foo == stringToTest sẽ gọn gàng hơn foo.toString () === stringToTest.
Crispen Smith

2
@Alternatex Nếu vấn đề là rõ ràng, họ không nên làm cho nó TRIPLE bằng! Không có người mới bắt đầu hiểu nó. Ít nhất dấu bằng kép được biết đến từ các ngôn ngữ khác. Ngoài ra, there is no reasonable situationlà một sai sót tổng thể. Hãy nghĩ về các loại Javascript (bản địa) NumberString. Sự tồn tại của chúng chứng minh các tác giả Javascript đã nghĩ đến một số trường hợp sử dụng nhất định ==. Bạn có thực sự nghĩ rằng new String('hi') === 'hi'đánh giá falselà rất rõ ràng? Vui lòng viết đoạn mã kiểm tra đối số hàm của bạn để chống lại 'hi'việc chấp nhận cả Chuỗi và chuỗi và cho tôi biết điều đó rõ ràng.
Stijn de Witt

25

JSLint vốn có tính phòng thủ nhiều hơn so với cú pháp Javascript cho phép.

Từ tài liệu JSLint:

Các ==!=khai thác làm kiểu ép buộc trước khi so sánh. Điều này thật tệ bởi vì nó ' \t\r\n' == 0là sự thật. Điều này có thể che dấu các lỗi loại.

Khi so sánh với bất kỳ giá trị nào sau đây, hãy sử dụng toán tử ===or !==(không thực hiện nhập kiểu ép buộc):0 '' undefined null false true

Nếu bạn chỉ quan tâm rằng một giá trị là truthy hoặc falsy , sau đó sử dụng các hình thức ngắn. Thay vì

(foo != 0)

chỉ nói

(foo)

và thay vì

(foo == 0)

Nói

(!foo)

Các toán tử ===!==được ưu tiên.


8
Tôi phải kết luận rằng những người từ JSLint làm việc trong một tháp ngà rất cao mà họ không bao giờ thoát ra được. Javascript được thiết kế để sử dụng với ==toán tử. Các ===là một trường hợp đặc biệt ... JSLint cố gắng để làm cho nó có vẻ như sử dụng ==bằng cách nào đó sẽ là sai lầm ... Tuy nhiên, hãy thử này: var x = 4, y = new Number(4); if (x == y) {alert('Javascript depends on == just embrace it!');}. Các kiểu nguyên thủy có các lớp tương ứng thay thế cho chúng ( Number, String) và Javascript phụ thuộc vào ==toán tử để so sánh các lớp này tự nhiên.
Stijn de Witt

17

Hãy nhớ rằng JSLint thực thi một người ý tưởng về JavaScript tốt nên là gì. Bạn vẫn phải sử dụng ý thức chung khi thực hiện các thay đổi mà nó đề xuất.

Nói chung, so sánh loại và giá trị sẽ làm cho mã của bạn an toàn hơn (bạn sẽ không gặp phải hành vi không mong muốn khi chuyển đổi loại không thực hiện những gì bạn nghĩ).


4
Thêm vào đó, nó không thể thông minh theo ngữ cảnh như một lập trình viên. Nó chỉ làm việc trên cơ sở rằng hầu hết người dùng bị vấp lên theo loại tự động chuyển đổi vốn có trong hệ thống (như bạo lực - "help help tôi đang bị đàn áp!")
Rudu

14

Triple-bằng khác với double-bằng vì ngoài việc kiểm tra xem hai cạnh có cùng giá trị hay không, triple-bằng còn kiểm tra xem chúng có cùng kiểu dữ liệu hay không.

Như vậy ("4" == 4)là đúng, ngược lại ("4" === 4)là sai.

Triple-bằng cũng chạy nhanh hơn một chút, vì JavaScript không phải mất thời gian thực hiện bất kỳ chuyển đổi kiểu nào trước khi đưa ra câu trả lời cho bạn.

JSLint cố tình làm cho mã JavaScript của bạn càng chặt chẽ càng tốt, với mục đích giảm thiểu các lỗi khó hiểu. Nó làm nổi bật loại điều này để cố gắng giúp bạn viết mã theo cách buộc bạn phải tôn trọng các kiểu dữ liệu.

Nhưng điều tốt về JSLint là nó chỉ là một hướng dẫn. Như họ nói trên trang web, nó sẽ làm tổn thương cảm xúc của bạn, ngay cả khi bạn là một lập trình viên JavaScript rất giỏi. Nhưng bạn không nên cảm thấy bắt buộc phải làm theo lời khuyên của nó. Nếu bạn đã đọc những gì nó nói và bạn hiểu nó, nhưng bạn chắc chắn rằng mã của bạn sẽ không bị hỏng, thì bạn không cần phải thay đổi bất cứ điều gì.

Bạn thậm chí có thể yêu cầu JSLint bỏ qua các loại kiểm tra nếu bạn không muốn bị tấn công bởi những cảnh báo rằng bạn sẽ không làm gì cả.


3
Tôi không hỏi "===" là gì, vì vậy tôi không chắc tại sao bạn trả lời nó.
Metropolis

8
@Metropolis: nếu không có lý do nào khác, thì làm nền trong trường hợp người khác đọc câu trả lời mà người không biết. Tuy nhiên, tôi đã cố gắng trả lời câu hỏi của bạn trong các đoạn sau đó.
Spudley

@Spudley + 1 để biết thông tin bổ sung và hữu ích
Ben Junior

1
vâng, nó nhanh hơn 10-100 lần: kiểm tra tốc độ jsperf
vladkras

8

Trích dẫn từ http://javascript.crockford.com/code.html :

Các toán tử === và! ==.

Hầu như luôn luôn tốt hơn nếu sử dụng các toán tử === và! ==. Toán tử == và! = Thực hiện cưỡng chế kiểu. Đặc biệt, không sử dụng == để so sánh với các giá trị giả.

JSLint rất nghiêm ngặt, 'webjslint.js' của họ thậm chí không vượt qua xác nhận của chính họ.


Làm rõ tốt đẹp. Điều đó đúng, về việc webjslint.jskhông xác thực - mặc dù hầu hết các lỗi tôi thấy hiện nay đều liên quan đến khoảng cách. Rõ ràng, người ta phải sử dụng ý thức chung và phán đoán hợp lý khi xem xét JavaScript bằng JSLint.
hotshot309 28/12/11

Việc sử dụng từ này alwaystự động loại bỏ câu trích dẫn này là sự khôn ngoan. Các lập trình viên thông minh không giáo điều. Họ sử dụng những gì tốt nhất trong tình huống nhất định. Và họ hoan nghênh và đón nhận bất kỳ công cụ nào được xây dựng trong cốt lõi của ngôn ngữ, chứ không chỉ loại bỏ nó bằng a just never touch it. Điểm mấu chốt: Mã của tôi ngắn hơn (và không chỉ lưu một =ký tự), do đó trang web của tôi tải nhanh hơn, với chi phí băng thông ít hơn, do đó người dùng của tôi được phục vụ tốt hơn.
Stijn de Witt

4

Nếu bạn muốn kiểm tra độ giả dối. JSLint không cho phép

if (foo == null)

nhưng không cho phép

if (!foo)

Sử dụng ===, mà JSLint khuyến nghị.
clickbait

1
@NarawaGames Giải pháp này hoàn toàn có thể chấp nhận được.

Câu trả lời này là không tốt. Vấn đề là cả hai đều có nghĩa khác. foo == nullkiểm tra null hoặc không xác định. !fookiểm tra null, undefined, 0 và rỗng.
Markos

@Markos Câu trả lời này có nghĩa là một sự thay thế hữu ích để làm cho JSLint hài lòng và giữ nguyên logic mã của bạn, không phải là một tương đương chính xác. Đây là lý do tại sao tôi có tiền tố câu trả lời với "Nếu kiểm tra falsyness"
nano2nd

3

Để giúp giải thích câu hỏi này và cũng giải thích tại sao NetBeans (từ) 7.3 đã bắt đầu hiển thị cảnh báo này, đây là một đoạn trích từ phản hồi trên trình theo dõi lỗi NetBeans khi ai đó báo cáo đây là lỗi:

Nên sử dụng === thay vì == trong JavaScript.

Toán tử == và! = Thực hiện cưỡng chế nhập trước khi so sánh. Điều này không tốt vì nó khiến '\ t \ r \ n' == 0 là true. Điều này có thể che dấu các lỗi loại. JSLint không thể xác định một cách đáng tin cậy xem == có được sử dụng đúng hay không, vì vậy tốt nhất là không sử dụng == và! = Và luôn sử dụng các toán tử === và! == đáng tin cậy hơn để thay thế.

Tài liệu tham khảo


1
Tôi cũng tìm thấy lỗi này bằng cách sử dụng Netbeans. Thật kỳ lạ là họ sẽ xử lý điều này với mức độ nghiêm trọng cảnh báo do trường hợp ví dụ kỳ lạ mà họ cung cấp.
omikes

1
Ý tôi là, nó đúng, nhưng có nhiều trường hợp sử dụng trong đó người ta biết rằng hai thứ được so sánh sẽ cùng loại, vì vậy có vẻ lạ là do trường hợp kỳ lạ này mà ký tự xuống dòng có thể được so sánh với số 0 là lý do tất cả các cách sử dụng == bị coi là sai. tôi đang tìm hiểu mặc dù điều đó === nhanh hơn vì không có chuyển đổi loại nào được thực hiện. Tôi ngạc nhiên là tôi đã không phát hiện ra điều này trước netbeans.
omikes

@oMiKeY Vâng, tôi hiểu ý bạn, lẽ ra họ có thể đưa ra những ví dụ thực tế hơn!
EM-Creations

2

Nó thực sự không thể gây ra vấn đề, nó chỉ là cho bạn lời khuyên. Hoặc là lấy đi hoặc là bỏ lại. Điều đó nói rằng, tôi không chắc nó thông minh đến mức nào. Cũng có thể có những bối cảnh mà nó không thể hiện nó như một vấn đề.


nhưng tại sao từ "Dự kiến" được sử dụng? Điều đó làm cho nó có vẻ như bạn nên luôn luôn làm điều này.
Metropolis

4
Người đánh giá đang tìm kiếm một phản hồi hợp lệ vì nó đang cố gắng xác nhận nó. Nếu nó không nhận được phản hồi hợp lệ, thì đó không phải là những gì nó mong đợi. Trình xác thực bắt đầu với giả định rằng mọi thứ đều ổn và sau đó chỉ ra các lỗi khi nó duyệt qua mã. Nó không nhất thiết phải hiểu thế nào là một phản hồi không hợp lệ, nó chỉ biết khi thấy một phản hồi không hợp lệ. Nó cũng có thể hoạt động ngược lại, cố tình tìm kiếm mã xấu theo quy tắc của những gì là xấu. Danh sách trắng và danh sách đen.
Rushyo

Câu hỏi đặt ra là "Điều đó có thực sự có ý nghĩa không?". Đưa ra câu hỏi đó, có, nó có. Ngoài ra, đó là năm năm trước . Chúa ơi.
Rushyo
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.