Javascript autobox?

Mentre lavoravo su un altro problema, ho creato questo violino:

http://jsfiddle.net/tr2by/

function foo() { // console.log(_.isBoolean(this)); console.log(this === true); } foo.call(true); // object:[object Boolean] foo.apply(true); // object:[object Boolean] 

Questo è un esempio di auto-boxing?

Passando da un tipo di valore a un tipo di riferimento.

Ecco una wikipedia def.

Prima di tutto suppongo che tu stia parlando della conversione automatica di valori primitivi in ​​oggetti. Questo succede in due casi in JavaScript:

  1. Quando si passa un valore primitivo come this valore a .call o .apply (non in modalità rigorosa).
  2. Quando stai tentando di accedere a una “proprietà” di un valore primitivo, ad es. "foo bar".split() .

Nel primo caso la conversione è permanente, cioè this farà effettivamente riferimento a un object, nel secondo la conversione avviene solo internamente per la durata della valutazione

Se non sei interessato ai dettagli della conversione, puoi ignorare il resto della risposta.


1. Valore primitivo come this

Quando una funzione è exectued e il suo valore non è un object, viene convertito in uno, almeno in modalità non rigida. Questo è descritto in §10.4.3 Immissione del codice funzione [spec] nella documentazione di ECMAScript 5.1:

I seguenti passaggi vengono eseguiti quando il controllo accede al contesto di esecuzione per il codice funzione contenuto nell’object funzione F , un chiamante fornito thisArg e un thisArg argumentsList fornito dal chiamante:

  1. Se il codice funzione è un codice rigoroso, impostare ThisBinding su thisArg .
  2. Altrimenti se thisArg è null o undefined , imposta ThisBinding sull’object globale.
  3. Altrimenti se Type(thisArg) non è Object , imposta ThisBinding su ToObject(thisArg ).
    […]

Come puoi vedere nel passaggio tre, il valore viene convertito in un object chiamando ToObject [spec] .

2. Accesso alla proprietà

Qualcosa di simile accade quando si tenta di accedere alle proprietà ( §11.2.1 Property Accessors [spec] ). La parte qui citato spiega come viene valutata l’espressione foo[bar] , ovvero come viene valutata l’accesso alla proprietà con la notazione della parentesi. La parte a cui siamo interessati si applica anche alla notazione a punti.

La MemberExpression : MemberExpression [ Expression ] produzione MemberExpression : MemberExpression [ Expression ] viene valutata come segue:

  1. Lasciare che baseReference sia il risultato della valutazione di MemberExpression .
  2. Lasciare baseValue essere GetValue(baseReference) .
    […]

8. Restituisce un valore di tipo Reference cui valore di base è baseValue e il cui nome di riferimento è propertyNameString e il cui flag di modalità strict è strict .

Il passo importante è l’ultimo: indipendentemente da ciò che MemberExpression valuta, viene convertito in un valore di tipo Reference [spec] . Questo è un tipo di dati utilizzato solo nella specifica e contiene informazioni aggiuntive su come il valore effettivo dovrebbe essere recuperato dal riferimento (da non confondere con i riferimenti object nel codice JavaScript reale!).

Per ottenere il valore / risultato “reale” da tale riferimento, viene richiamata la funzione interna GetValue(V) (§8.7.1) [specifica] (proprio come nel passaggio 2 dell’algoritmo sopra), dove si dice:

Il seguente metodo interno [[Get]] viene utilizzato da GetValue quando V è un riferimento di proprietà con un valore di base primitivo. Si chiama usando base come suo valore e con la proprietà P come argomento. I seguenti passi sono presi:

  1. Sia O essere ToObject(base) .
    […]

Esempio:

Supponiamo di avere l’espressione

 var foo = "BAR".toLowerCase(); 

Questa è un’espressione di assegnazione che viene valutata come segue:

La produzione AssignmentExpression : LeftHandSideExpression = AssignmentExpression viene valutata come segue:

  1. Lascia che lref sia il risultato della valutazione di LeftHandSideExpression .
  2. Lasciare che rref sia il risultato della valutazione di AssignmentExpression .
  3. Sia rval be GetValue(rref) .
    […]

Passo 1: Viene valutato il lato sinistro, che è l’identificatore foo . Il modo in cui esattamente gli identificatori vengono risolti non è importante per questo.
Passaggio 2: viene valutato il lato destro, ovvero "BAR".toLowerCase() . Il risultato interno di tale valutazione sarà un valore di riferimento, simile a:

 REFERENCE = { base: "BAR", propertyNameString: "toLowerCase", strict: false } 

e memorizzato in rref .

Passaggio 3: viene chiamato GetValue(rref) . La base del riferimento è il valore "BAR" . Poiché questo è un valore primitivo, verrà chiamato ToObject per convertirlo in un object String temporaneo . Inoltre, il riferimento è in realtà un accesso alla proprietà , quindi GetValue chiamerà il metodo toLowerCase sull’object String e restituirà il risultato del metodo.

Javascript inserisce this argomento fornito per call e apply in modalità non rigida. Da MDN :

se il metodo è una funzione in codice di modalità non-strict, null e undefined verranno sostituiti con l’object globale e i valori primitivi saranno racchiusi.