2012-02-17 27 views
8

Trong this answer có một hàm đơn giản sẽ trả về mảng bằng nhau cho các mảng chứa giá trị nguyên thủy.Tại sao hoặc như thế nào điều này chứng minh sự bình đẳng mảng JavaScript?

Tuy nhiên, tôi không chắc chắn lý do tại sao nó hoạt động. Đây là hàm:

function arrays_equal(a,b) { return !!a && !!b && !(a<b || b<a); } 

Tôi chủ yếu quan tâm đến nửa thứ hai; bit này:

!(a<b || b<a) 

Tại sao <> làm việc khi so sánh các mảng nhưng == không?

Làm cách nào nhỏ hơn và lớn hơn các phương thức hoạt động trong JavaScript?

Trả lời

10

Với </>, các mảng được chuyển đổi thành chuỗi đầu tiên và do đó không cung cấp phương pháp kiểm tra bình đẳng đáng tin cậy.

== không hoạt động vì các đối tượng được kiểm tra bằng cách tham khảo:

[] == []; // false, two separate objects 

var a = []; 
a == a; // true, refer to the same object 

Bí quyết </> là thiếu sót:

var a = [1, [2, 3]], 
    b = [[1, 2], 3]; 

!(a<b || b<a); // true 

này đánh giá để true, vì cả hai đều chuyển thành chuỗi "1,2,3" trước khi được kiểm tra (</> không hoạt động "trực tiếp" cho các đối tượng).

Về cơ bản, bạn đang so sánh sự bình đẳng của các chuỗi. Đối với chuỗi, a == b thực sự giống như !(a<b || b<a) - </> cho chuỗi kiểm tra mã ký tự, do đó, hai chuỗi bằng nhau không phải là "nhỏ hơn" hoặc "lớn hơn" vì đó không phải là trường hợp cho bất kỳ mã ký tự nào trong chuỗi.

+0

+1 nhận những điều mới mẻ mỗi ngày trong JS. Ngôn ngữ đáng yêu – Sarfraz

+0

@Sarfraz: Vâng, cho đến khi bạn khám phá những thứ như thế này sau một vài lần gỡ lỗi khó chịu ... – pimvdb

+0

Gần đây bạn đã bắt đầu học nó ** nghiêm túc **, tiến lên :). Bạn nên có một blog bằng cách này :) – Sarfraz

4

Bạn có thể so sánh hai đối tượng bất kỳ bằng cách sử dụng ==. Nhưng vì> và < không được xác định cho các đối tượng, chúng được chuyển đổi thành chuỗi. Do đó, [1,2,3]>[2,1,3] thực sự đang làm "1,2,3">"2,1,3"

+1

điều này là không chính xác. Chuyển đổi không phải lúc nào cũng thành chuỗi. [11.8.5] (http://es5.github.com/#x11.8.5) quy định rằng chuyển đổi đối tượng xảy ra với gợi ý kiểu '" số "' do đó 'arrays_equal (ngày mới (1), 1)' là 'đúng '. –

+0

Cảm ơn; và với Mike để làm rõ trong bình luận của mình! –

5

Tuy nhiên, tôi không chắc chắn lý do tại sao nó hoạt động.

Nó không hoạt động. Hãy xem xét

arrays_equal(["1,2"], [1,2]) 

tạo ra đúng mặc dù bằng bất kỳ định nghĩa nào về sự bình đẳng mảng dựa trên so sánh yếu tố, chúng khác nhau.

arrays_equal([[]], []) 

arrays_equal([""], []) 

cũng có mặt tích cực giả mạo.

Đơn giản chỉ cần thêm length kiểm tra sẽ không giúp được minh chứng bởi

arrays_equal(["1,2",3], [1,"2,3"]) 

arrays_equal(
    ["",","], 
    [",",""]) 

EDIT:

Nếu bạn muốn có một cách gọn gàng để kiểm tra sự tương đồng về cấu trúc, tôi đề nghị:

function structurallyEquivalent(a, b) { 
    return JSON.stringify(a) === JSON.stringify(b); 
} 

Nó không dừng lại sớm trên các đầu vào rõ ràng là khác nhau - nó đi cả hai đồ thị đối tượng bất kể chúng khác nhau như thế nào, nhưng cũng có chức năng trong OP.

Một caveat: khi bạn đang sử dụng không có nguồn gốc JSON.stringify, nó có thể làm những điều xa lạ đối với đầu vào theo chu kỳ như:

var input = []; 
input[0] = input; 
+1

Ngay cả đối với nguyên thủy, 'JSON.stringify' có thể không hoàn toàn đáng tin cậy. Xem xét '[,]' và '[null]'. – pimvdb

+0

@pimvdb, Chắc chắn rồi. Nó conflates 'null' và' undefined'/elipsis nhưng cũng như vậy JavaScript '=='. Không có gì trong OP thể hiện một sở thích cho '===' trên '=='. –

+0

Cảm ơn, câu trả lời của bạn đã hỗ trợ thêm cho sự hiểu biết của tôi cùng với @ pimvdb's. –

Các vấn đề liên quan