2015-05-19 7 views
10

Stavo facendo un po 'di test convertendo i valori in intero in javascript e stampando l'output nella console quando mi sono imbattuto in questo strano comportamento.Perché utilizzare l'operatore unario + su un array fornisce risultati incoerenti in javascript?

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

ho pensato che i valori venivano convertite parseInt, ma abbiamo scoperto che non era così sono andato alla tabella di conversione javascript http://www.w3schools.com/js/js_type_conversion.asp

Questo mi dà una migliore idea di come vengono eseguite le conversioni. Tronchi con questa tabella

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

Quindi verrà aggiustata prendono il primo valore della matrice e convertire utilizzando le regole specificate. Le regole di parseInt non si applicano.

Ho testato per raggiungere questa conclusione. Puoi nidificarlo tutto ciò che vuoi, ti darà lo stesso risultato.

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

Allora ho pensato, ok, se questo è il caso

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

questi sono i valori previsti dalla tabella di conversione javascript a intero, ma risulta

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

L'ultimo è il il più strano perché false viene convertito in 0, non in NaN. Qualcuno può spiegare lo strano comportamento o spiegare come viene eseguita questa conversione?

risposta

6

Il Unary + operator utilizza internamente l'operazione astratta ToNumber.

Il ToNumber abstract operation, quando applicato ad oggetti, chiama toString metodo dell'oggetto (attraverso il [[DefaultValue]] internal method) e poi ri-applica il operazione ToNumber sulla rappresentazione stringa risultante.

La cosa interessante qui è il metodo toString di Array. Notare che [false].toString() è completamente diverso da [undefined].toString() o [null].toString(). Quando ispezioniamo le specifiche per Array.prototype.toString, vediamo che internamente utilizza Array.prototype.join. Fase 8 del join dell'algoritmo dice:

  1. Se element0 è undefined o null, lasciare che R essere una stringa vuota; altrimenti, Let R be ToString (element0).

Pertanto, qualsiasi matrice contenente un singolo null o undefined stringifies alla stringa vuota (che ToNumber numero-ifies a 0), mentre altri valori in stringa a qualche altra stringa (che poi sarà numero- se a NaN se la stringa non è numerica).

+[undefined] è lo stesso +"", mentre +[false] è lo stesso +"false".

+0

Hah, sei arrivato più veloce di me. Avevo quasi finito con 'GetValue' e sul mio cammino' ToNumber'. Le specifiche ECMA sono sorprendentemente difficili da leggere. – Luaan

Problemi correlati