2015-05-19 18 views
10

Tôi đã thực hiện một số thử nghiệm chuyển đổi giá trị thành số nguyên trong javascript và in đầu ra trong bảng điều khiển khi tôi bắt gặp hành vi lạ này.Tại sao sử dụng toán tử đơn nhất + trên một mảng cho kết quả không nhất quán trong javascript?

console.log(+[]) ==> 0 
console.log(+[123]) ==> 123 
console.log(+['123']) ==> 123 
console.log(+[123, 456]) ==> NaN 
console.log(+['123asdf']) ==> NaN 

tôi nghĩ các giá trị đã được chuyển đổi sử dụng parseInt nhưng hóa ra nó không được vì vậy tôi đã đi đến bảng chuyển đổi javascript http://www.w3schools.com/js/js_type_conversion.asp

này cho tôi một ý tưởng tốt hơn về cách chuyển đổi được thực hiện. Căn cứ vào bảng này

[] => 0 
[20] => 20 
[10,20] => NaN 
["twenty"] =>NaN 
["ten","twenty"] => NaN 

Vì vậy, họ lấy giá trị đầu tiên của mảng và chuyển đổi nó bằng các quy tắc được chỉ định. Các quy tắc của parseInt không áp dụng.

Tôi đã thử nghiệm để đạt được kết luận này. Bạn có thể lồng nó tất cả những gì bạn muốn, nó sẽ cho bạn kết quả tương tự.

console.log(+[[[[[[[[[[[10]]]]]]]]]]]) => 10 

Vì vậy, sau đó tôi nghĩ, ok nếu đó là trường hợp

console.log(+[undefined]) will return NaN 
console.log(+[null]) will return 0 
console.log(+[false]) will return 0 

đó là những giá trị dự kiến ​​từ bảng chuyển đổi javascript để nguyên nhưng hóa ra

console.log(+[undefined]) => 0 
console.log(+[null]) => 0 
console.log(+[false]) => NaN 

cuối cùng là kỳ lạ nhất vì sai được chuyển thành 0, không thành NaN. Ai đó có thể giải thích hành vi lạ hoặc giải thích cách chuyển đổi này được thực hiện?

Trả lời

6

Unary + operator sử dụng nội bộ hoạt động trừu tượng ToNumber.

Các ToNumber abstract operation, khi áp dụng cho các đối tượng, gọi phương thức của đối tượng toString (bằng cách của [[DefaultValue]] internal method) và sau đó lại áp dụng ToNumber hoạt động trên các đại diện chuỗi kết quả.

Điều thú vị ở đây là phương pháp toString của Array. Lưu ý rằng [false].toString() hoàn toàn khác với [undefined].toString() hoặc [null].toString(). Khi chúng tôi kiểm tra các đặc điểm kỹ thuật cho Array.prototype.toString, chúng tôi thấy rằng nội bộ nó sử dụng Array.prototype.join. Bước 8 của thuật toán join nói:

  1. Nếu element0undefined hoặc null, chúng ta hãy R là chuỗi rỗng; nếu không, hãy để RToString (element0).

Vì vậy, bất kỳ mảng chứa một đơn null hoặc undefined stringifies với chuỗi rỗng (mà ToNumber số-ifies để 0), trong khi giá trị khác sẽ stringify một số chuỗi khác (mà sau đó sẽ number- ify đến NaN nếu chuỗi không phải là số).

+[undefined] giống với +"", trong khi +[false] cũng giống như +"false".

+0

Hah, bạn đến đó nhanh hơn tôi. Tôi đã được thực hiện với 'GetValue' và trên con đường của tôi thông qua' ToNumber'. Thông số kỹ thuật của ECMA rất khó đọc. – Luaan

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