2012-01-21 17 views
5

Ho visto questo abbastanza divertente screencast ieri su alcune stranezze in linguaggi come Ruby e JavaScript e il ragazzo dimostra che:Perché Array + Array è uguale a stringa vuota?

[] + [] -> "" // returns empty string 

non molto evidente ...

ho deciso di andare a il per avere maggiori informazioni. Ho iniziato con l'implementazione + dell'operatore (p.75) che dice:

11.6.1 l'operatore di addizione (+)

L'operatore di addizione o esegue la concatenazione di stringhe o aggiunta numerica.
L'espressione di produzione Additive: AdditiveExpression + MultiplicativeExpression viene valutata come segue:
1. Sia lref il risultato della valutazione di AdditiveExpression.
2. Sia lval essere GetValue (lref).
3. Sia rref il risultato della valutazione di MultiplicativeExpression.
4. Sia rval be GetValue (rref).
5. Sia lprim be ToPrimitive (lval).
6. Sia rprim be ToPrimitive (rval).
7. Se Type (lprim) è String o Type (rprim) è String, quindi
a. Restituisce la stringa che è il risultato della concatenazione di ToString (lprim) seguito da ToString (rprim)
8. Restituire il risultato dell'applicazione dell'operazione di aggiunta a ToNumber (lprim) e ToNumber (rprim). Vedere la nota sotto 11.6.3.

NOTA1 Nelle chiamate a ToPrimitive non viene fornito alcun suggerimento nei passaggi 5 e 6. Tutti gli oggetti nativi ECMAScript tranne gli oggetti Date gestiscono l'assenza di un suggerimento come se fosse stato fornito il numero di suggerimento; Gli oggetti Date gestiscono l'assenza di un suggerimento come se fosse stato fornito il suggerimento String. Gli oggetti host possono gestire l'assenza di un suggerimento in qualche altro modo.

NOTA 2 Il passaggio 7 differisce dal punto 3 dell'algoritmo di confronto per gli operatori relazionali (11.8.5), utilizzando l'operazione logica o operativa anziché l'operazione logica e.

La mia ipotesi è che il punto 7 è stato raggiunto in qualche modo attraverso diverse valutazioni/conversioni come descritto in precedenza, ma non riesco a capire cosa sta realmente happenning ...

Qualcuno può fornire una spiegazione molto semplice per Questo ?


Sono disposto a capire tutto questo un po 'meglio al fine di cercare di rispondere perché:

[] + {} -> [object Object] 
{} + [] -> 0 

risposta

7
  1. Let lprim essere ToPrimitive (lval).
  2. Lascia che rprim sia ToPrimitive (rval).

Poiché nessun suggerimento viene fornito per ToPrimitive:

Quando il metodo interno [[DefaultValue]] di O viene richiamata senza suggerimento, quindi si comporta come se il suggerimento fosse Numero, a meno che O sia un oggetto Data (vedere 15.9.6), nel qual caso si comporta come se il suggerimento fosse Stringa.

Quindi è uguale a chiamare con un pizzico numero:

When the [[DefaultValue]] internal method of O is called with hint Number, the following steps are taken: 
1. Let valueOf be the result of calling the [[Get]] internal method of object O with argument "valueOf". 
2. If IsCallable(valueOf) is true then, a. Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and an empty argument list. b. If val is a primitive value, return val. 
3. Let toString be the result of calling the [[Get]] internal method of object O with argument "toString". 
4. If IsCallable(toString) is true then, a. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list. b. If str is a primitive value, return str. 
5. Throw a TypeError exception. 

Dal momento che il valore di ritorno di [].valueOf() non è un primitivo, va a [].toString() che restituisce "".

Questo vale anche per oggetto oggetti, tranne il .toString di un oggetto restituisce [object Object] mentre .toString di un array restituisce .join(",")


{} + []

Il {} non viene trattato come un oggetto qui ma come blocco vuoto. Così il codice che viene eseguito è:

{} 
+[]; //Same as +[] (Number([])) which is 0 

Per risolvere l'ambiguità e ottenere risultato normale da {} + [] uso

({}) + [] o ({} + [])

codice di divertente:

{} ! [] //false 
({}) ! [] //SyntaxError 
+0

ha più senso ora. Le specifiche possono essere belle da inserire ma ora hanno dei lead. Grazie. –

+0

@DidierGhys sì, attento con l'oggetto letterale, javascript è molto desideroso di trattarli come blocchi ovunque possa. – Esailija

+0

Lo terrò a mente. –