2017-12-03 13 views
7

Tôi đang phải vật lộn với sự hiểu biết như thế nào đoạn này hoạt động trên một mức độ cơ bảngì đang xảy ra trong sự so sánh này bình đẳng lỏng lẻo của 2 mảng trống

if([] == ![]){ 
console.log("this evaluates to true"); 
} 

Xin hãy giúp tôi hiểu nơi mà tôi đã nhận nó sai. Suy nghĩ của tôi:

  1. Trước tiên, nhà điều hành ưu tiên để ! đánh giá trước ==.
  2. Tiếp theo ToPrimitive được gọi và [] chuyển thành chuỗi trống.
  3. ! thông báo của nhà điều hành rằng cần phải chuyển đổi "" thành boolean để có giá trị đó và biến nó thành false sau đó phủ nhận thành true.
  4. == thích để so sánh số như vậy trong suy nghĩ của tôi true làm 1[] được chuyển thành "" và sau đó 0

Tại sao nó lại làm việc sau đó? Tôi đã làm sai ở đâu?

+1

'! []' Là 'false', không phải' true', vì '[]' là một đối tượng. 'ToPrimitive' không được gọi trước khi phủ định, nó được gọi ở điểm phủ định, nếu có. '==' ép buộc mảng đầu tiên. – Xufox

+0

yes! [] IS sai nhưng CÁCH hoạt động? TẠI SAO nó sai? Đây là những câu hỏi thực sự. Lời giải thích rằng mảng trống là một đối tượng không thuyết phục tôi xin lỗi –

+2

@KonradAlbrecht, nhưng đó là lời giải thích. Nếu bạn không hài lòng với điều đó, thì đó thực sự là vấn đề của bạn. Trong JavaScript * tất cả * đối tượng (ngoại trừ 'null' không thực sự là một đối tượng và' document.all', là một câu chuyện hoàn toàn khác) đều là sự thật. Không có gì để hiểu về điều đó, nó là [a given] (https://developer.mozilla.org/en-US/docs/Glossary/Truthy). Mảng là các đối tượng, và vì vậy '[]' là sự thật. – trincot

Trả lời

9

Tại sao lại hoạt động?

TLDR:

[] == ![] 
     //toBoolean [1] 
[] == !true 
[] == false 
//loose equality round one [2] 
//toPrimitive([]); toNumber(false) [3] 
"" == 0 
//loose equality round two 
//toNumber("") [4] 
0 === 0 
true 

Một số giải thích:

1)

Đầu tiên là khai thác được ưu tiên để ! đánh giá trước khi ==

Negating something gọi phương thức toBoolean nội bộ vào "thứ gì đó" đầu tiên. Trong trường hợp này, đây là một đối tượng (như các mảng là các đối tượng) và cho rằng nó luôn trả về true mà sau đó được phủ nhận.

2)

Bây giờ nó tùy thuộc vào loose equalities special behaviour (xem Taurus câu trả lời để biết thêm):

Nếu A là một đối tượng (Mảng là Objects) và B là một Boolean nó sẽ làm:

ToPrimitive(A) == ToNumber(B) 

3)

toPrimitive([]) 

ToPrimitive (A) cố chuyển đổi đối số đối tượng của nó thành giá trị nguyên thủy, bằng cách cố gắng gọi các chuỗi khác nhau của các phương thức A.toString và A.valueOf trên A.

Chuyển đổi một mảng để nguyên thủy của nó được thực hiện bằng cách gọi toString (vì họ không có một phương pháp valueOf) mà về cơ bản là join(",").

toNumber(false) 

Kết quả là 1 nếu đối số là đúng. Kết quả là +0 nếu đối số là sai. Reference

Vì vậy false được chuyển thành +0

4)

toNumber("") 

Một StringNumericLiteral đó là trống hoặc chỉ chứa khoảng trắng được chuyển thành 0.

Vì vậy, cuối cùng "" được chuyển thành +0

tôi đã nhận được nó sai ở đâu?

Tại bước 1. Làm giảm một cái gì đó không gọi toPrimitive nhưng toBoolean ...

+0

Có phải 'ToPrimitive' không liên quan đến phân tích cú pháp'! [] '? –

+1

@David Hedlund không chỉ là 'toBoolean' –

+0

https://www.ecma-international.org/ecma-262/5.1/#sec-9.2 –

0

Đầu tiên, nhận ra rằng bạn đang so sánh hai loại khác nhau của các giá trị. Khi bạn sử dụng! [] Kết quả là sai. Bạn có mã (tại cốt lõi nó kết quả trong này):

if([] == false) 

Bây giờ là phần thứ hai: vì cả hai giá trị là kiểu khác nhau và bạn đang sử dụng "==", javascript chuyển đổi cả kiểu giá trị thành chuỗi (để làm chắc chắn rằng họ có cùng loại). Nó bắt đầu từ bên trái. Ở bên trái, chúng tôi có []. Vì vậy, javascript áp dụng hàm toString trên [], kết quả là sai. Hãy thử console.log([].toString())

Bạn sẽ nhận sai ở bên trái dưới dạng giá trị chuỗi. Ở bên phải, chúng ta có giá trị boolean false, và javascript thực hiện điều tương tự với nó. Nó sử dụng hàm toString trên false, điều này dẫn đến giá trị chuỗi sai. Hãy thử console.log(false.toString())

Điều này liên quan đến hai khái niệm cốt lõi: cách "==" hoạt động và tính tương hợp của toán tử "==" - cho dù nó bắt đầu từ trái hay phải.

Tính tương quan đề cập đến chức năng của nhà điều hành được gọi là: từ trái sang phải hoặc từ phải sang trái. Các nhà khai thác như == hoặc! hoặc + là các hàm sử dụng ký pháp tiền tố! Câu lệnh if ở trên sẽ dẫn đến sai nếu bạn sử dụng "===". Tôi hy vọng điều đó sẽ hữu ích.

+0

Bạn có thể vui lòng tham khảo các khiếu nại của mình không? –

+0

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/ Compar_Operators là hai liên kết đến nhà phát triển mozila, một trang web nổi tiếng. Và tôi đã học được những điều này trong việc hiểu những phần kỳ lạ của khóa học js. –

+0

Ý tôi là 'javascript chuyển cả hai loại giá trị thành chuỗi', 'Vì vậy, javascript áp dụng hàm toString trên [], kết quả là false', –

4

Câu trả lời được chấp nhận là không đúng (hiện nay, mặc dù), xem ví dụ sau:

if([5] == true) { 
 
console.log("hello"); \t 
 
}

Nếu mọi thứ thực sự là xử lý như các tiểu bang trả lời chấp nhận, sau đó [5] == true nên có được đánh giá là true vì mảng [5] sẽ được chuyển thành đối số chuỗi của nó ("5") và chuỗi "5" là trung thực (Boolean("5") === truetrue), vì vậy true == true phải đúng.

Nhưng điều này rõ ràng không phải là trường hợp vì điều kiện không đánh giá là true.

Vì vậy, những gì đang thực sự xảy ra là:

1.![] sẽ chuyển đổi toán hạng của nó để một boolean và sau đó lật rằng giá trị boolean, mỗi đối tượng là truthy, vì vậy ![] sẽ đánh giá để false.

Tại thời điểm này, việc so sánh trở nên [] == false


2. gì được vào chơi sau đó là những quy tắc 2, clearly stated trong # 6 trong số kỹ thuật cho các thuật toán Tóm tắt bình đẳng So sánh:

  1. Nếu loại (x) là boolean, trả về kết quả của phép so sánh ToNumber (x) == y.
  2. Nếu Kiểu (y) là boolean, trả lại kết quả của việc so sánh x == ToNumber (y)

Tại thời điểm này, việc so sánh trở nên [] == 0.


3. Sau đó, nó là quy tắc này:

Nếu Type (x) là đối tượng và Type (y) là một trong hai String hoặc Number, trả lại kết quả của việc so sánh ToPrimitive (x) == y.

Như @Jonas_W tuyên bố, một ToPrimitive của mảng sẽ gọi toString của nó, mà sẽ trả về một danh sách bằng dấu phẩy của nội dung của nó (tôi quá đơn giản).

Tại thời điểm này, so sánh trở thành "" == 0.


4. Và cuối cùng (tốt, hầu như), quy tắc này:

Nếu Type (x) là String và Type (y) là Number, trả lại kết quả của việc so sánh ToNumber (x) == y.

Chuỗi rỗng được chuyển đổi thành một số là 0 (Number("") == 0true).

Tại thời điểm này, so sánh trở thành 0 == 0.


5. Cuối cùng, quy tắc này sẽ được áp dụng:

Nếu Type (x) cũng giống như Kiểu (y), sau đó
.........
    Nếu Type (x) là Number, sau đó
.........
        Nếu x là giá trị số tương tự như y, tru trở lại e.


Và, đây là lý do tại sao việc so sánh để đánh giá true. Bạn cũng có thể áp dụng các quy tắc này cho ví dụ đầu tiên của tôi để xem lý do tại sao nó không đánh giá thành true.


Tất cả các quy tắc tôi đã nêu ở trên được nêu rõ ràng here trong thông số kỹ thuật.

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