Là một nhà toán học chuyên nghiệp, tôi thấy trong toán tử mẫu của Javscript == (còn gọi là "so sánh trừu tượng", "bình đẳng lỏng lẻo" ) một nỗ lực xây dựng mối quan hệ tương đương giữa các thực thể, bao gồm tính phản xạ , đối xứng và bắc cầu . Thật không may, hai trong số ba thuộc tính cơ bản này thất bại:
==không phải là phản xạ :
A == A có thể sai, vd
NaN == NaN // false
==không mang tính bắc cầu :
A == Bvà B == Ccùng nhau không ngụ ý A == C, ví dụ
'1' == 1 // true
1 == '01' // true
'1' == '01' // false
Chỉ có tài sản đối xứng tồn tại:
A == Bngụ ý B == A, vi phạm có lẽ là không thể tưởng tượng trong mọi trường hợp và sẽ dẫn đến nổi loạn nghiêm trọng;)
Tại sao quan hệ tương đương có vấn đề?
Bởi vì đó là loại quan hệ phổ biến và phổ biến nhất, được hỗ trợ bởi nhiều ví dụ và ứng dụng. Ứng dụng quan trọng nhất là phân rã các thực thể thành các lớp tương đương , bản thân nó là một cách hiểu rất thuận tiện và trực quan để hiểu các mối quan hệ. Và việc không tương đương dẫn đến việc thiếu các lớp tương đương, điều này dẫn đến việc thiếu trực giác và sự phức tạp không cần thiết được biết đến.
Tại sao nó là một ý tưởng khủng khiếp để viết ==cho một mối quan hệ không tương đương?
Bởi vì nó phá vỡ sự quen thuộc và trực giác của chúng tôi, vì theo nghĩa đen, bất kỳ mối quan hệ thú vị nào về sự tương đồng, bình đẳng, đồng đẳng, đẳng cấu, bản sắc, v.v ... là một sự tương đương.
Chuyển đổi loại
Thay vì dựa vào sự tương đương trực quan, JavaScript giới thiệu chuyển đổi loại:
Toán tử đẳng thức chuyển đổi các toán hạng nếu chúng không cùng loại, sau đó áp dụng so sánh nghiêm ngặt.
Nhưng chuyển đổi loại được định nghĩa như thế nào? Thông qua một bộ quy tắc phức tạp với nhiều ngoại lệ?
Cố gắng xây dựng mối quan hệ tương đương
Booleans. Rõ ràng truevà falsekhông giống nhau và nên ở trong các lớp khác nhau.
Số. May mắn thay, sự bằng nhau của các số đã được xác định rõ, trong đó hai số khác nhau không bao giờ trong cùng một lớp tương đương. Trong toán học, đó là. Trong JavaScript, khái niệm số có phần bị biến dạng thông qua sự hiện diện của kỳ lạ hơn -0, Infinityvà -Infinity. Trực giác toán học của chúng tôi chỉ ra rằng 0và -0nên ở trong cùng một lớp (thực tế -0 === 0là vậy true), trong khi mỗi trường hợp là một lớp riêng biệt.
Số và Booleans. Cho các lớp số, chúng ta đặt booleans ở đâu? falsetrở nên tương tự 0, trong khi truetrở nên tương tự 1nhưng không có số khác:
true == 1 // true
true == 2 // false
Có logic nào ở đây để đặt truecùng với 1? Phải thừa nhận 1là khác biệt, nhưng cũng vậy -1. Cá nhân tôi không thấy bất kỳ lý do để chuyển đổi truesang 1.
Và nó thậm chí còn tồi tệ hơn:
true + 2 // 3
true - 1 // 0
Vì vậy, truethực sự được chuyển đổi thành 1một trong số tất cả các số! Nó có logic không? Có trực quan không? Câu trả lời còn lại là bài tập;)
Nhưng những gì về điều này:
1 && true // true
2 && true // true
Boolean chỉ xcó x && truecon người truelà x = true. Điều đó chứng tỏ rằng cả hai 1và 2(và bất kỳ số nào khác ngoài 0) chuyển đổi thành true! Những gì nó thấy là chuyển đổi của chúng tôi không khác tính chất quan trọng - là song ánh . Có nghĩa là hai thực thể khác nhau có thể chuyển đổi thành cùng một. Mà, tự nó, không phải là một vấn đề lớn. Vấn đề lớn nảy sinh khi chúng tôi sử dụng chuyển đổi này để mô tả mối quan hệ "giống nhau" hoặc "bình đẳng lỏng lẻo" của bất cứ điều gì chúng tôi muốn gọi nó. Nhưng có một điều rõ ràng - nó sẽ không phải là một mối quan hệ tương đương và nó sẽ không được mô tả bằng trực giác thông qua các lớp tương đương.
Nhưng chúng ta có thể làm tốt hơn không?
Ít nhất là về mặt toán học - chắc chắn là có! Một mối quan hệ tương đương đơn giản giữa booleans và số có thể được xây dựng chỉ với falsevà 0nằm trong cùng một lớp. Vì vậy, false == 0sẽ là bình đẳng lỏng lẻo không tầm thường.
Còn dây thì sao?
Chúng ta có thể cắt các chuỗi từ khoảng trắng ở đầu và cuối để chuyển đổi thành số, ngoài ra chúng ta có thể bỏ qua các số 0 ở phía trước:
' 000 ' == 0 // true
' 0010 ' == 10 // true
Vì vậy, chúng ta có một quy tắc đơn giản cho một chuỗi - cắt bớt các khoảng trắng và số 0 ở phía trước. Hoặc là chúng tôi nhận được một số hoặc chuỗi trống, trong trường hợp đó chúng tôi chuyển đổi thành số đó hoặc bằng không. Hoặc chúng tôi không nhận được một số, trong trường hợp đó chúng tôi không chuyển đổi và do đó không có mối quan hệ mới.
Bằng cách này, chúng tôi thực sự có thể có được một mối quan hệ tương đương hoàn hảo trên tổng số booleans, số và chuỗi! Ngoại trừ việc ... các nhà thiết kế JavaScript rõ ràng có ý kiến khác:
' ' == '' // false
Vì vậy, hai chuỗi mà cả hai chuyển đổi thành 0đột nhiên không giống nhau! Tại sao hay tại sao? Theo quy tắc, các chuỗi là lỏng lẻo chính xác khi chúng hoàn toàn bằng nhau! Không chỉ quy tắc này phá vỡ tính siêu việt như chúng ta thấy, mà còn là dư thừa! Điểm tạo ra một toán tử khác ==để làm cho nó hoàn toàn giống với toán tử kia là ===gì?
Phần kết luận
Toán tử đẳng thức lỏng lẻo ==có thể rất hữu ích nếu nó tuân theo một số định luật toán học cơ bản. Nhưng thật đáng buồn là nó không hữu dụng.