Differenza tra il tipo di stringa javascript e l’object stringa?

Ho lavorato con lo standard ECMA-262 ( ECMAScript Language Specification, 3a edizione, se è importante per questo – non ho trovato alcuna differenza tra la 3a e la 5a edizione su String Type / String Object).

C’è una cosa che mi sconcerta: la differenza tra il tipo di stringa e l’object stringa. Sì, conosco la differenza, nel senso che String Type è una sequenza di unità UTF-16 a 16 bit e String Object è un object predefinito con la sua proprietà Class class impostata su “String” e la sua proprietà Value interna impostata su un valore del tipo di stringa .

Ma leggendo le specifiche, il tipo di stringa non sembra esporre alcun metodo; cioè, è solo un valore senza proprietà aggiuntive. Prendi questo codice, tutto è esattamente come previsto:

document.writeln(typeof "foo"); // 'string' document.writeln(typeof new String("foo")); // 'object' 

Il primo tipo è il tipo di stringa effettivo e il secondo è il tipo di object (è un object di class String , ma il suo tipo di dati è object). Tuttavia, guardando questo:

 "foo".charAt(0); fooStrObj = new String("Foo"); fooStrObj.charAt(0); 

Entrambi sembrano esporre le stesse funzioni, ma non ci sono funzioni sul tipo di stringa definito nello standard ECMA-262; tutte le funzioni che espone provengono dall’object String.prototype (e non vedo alcun riferimento al fatto che il tipo di stringa espone magicamente tutte le proprietà e le funzioni dell’object String.prototype nello standard ECMA-262). Quindi i valori di tipo String Type vengono automaticamente promossi a un object String con il valore Type String originale come proprietà Value interna?

E se sono trattati esattamente allo stesso modo (che a tutti gli effetti sembrano essere), perché hanno due modi diversi di rappresentare una stringa ?

Le stringhe sono un tipo di valore in JS, quindi non possono avere alcuna proprietà associata a esse, nessun prototipo, ecc. Qualsiasi tentativo di accedere a una proprietà su di esse sta tecnicamente eseguendo la conversione JS [[ToObject]] (in sostanza nuova stringa) .

Un modo semplice per distinguere la differenza è (in un browser)

 a = "foo" ab = "bar" alert("ab = " + ab); //Undefined A = new String("foo"); Ab = "bar"; alert("Ab = " + Ab); // bar 

Inoltre mentre

 "foo" == new String("foo") 

è vero, è vero solo a causa delle conversioni implicite del tipo dell’operatore ==

 "foo" === new String("foo") 

avrà esito negativo.

È analogo alla differenza tra int e Integer in Java.

Secondo lo standard, le stringhe vengono automaticamente convertite in oggetti String quando si tenta di chiamare un metodo. Vedi ECMA 262-3 sezione 11.2.1 ; il passaggio 5 chiama ToObject (definito nella sezione 9.9).

11.2.1 Accessors di proprietà
[…]
La MemberExpression di produzione: MemberExpression [Expression] viene valutata come segue:

  1. Valuta MemberExpression.
  2. Chiama GetValue (Risultato (1)).
  3. Valuta Espressione.
  4. Chiama GetValue (Risultato (3)).
  5. Chiama ToObject (Risultato (2)).
  6. Chiama ToString (Risultato (4)).
  7. Restituisce un valore di tipo Reference il cui object di base è Result (5) e il cui nome di proprietà è Result (6).

9,9 ToObject

L’operatore ToObject converte il suo argomento in un valore di tipo Object in base alla seguente tabella:
[…]
Crea un nuovo object String la cui proprietà [[valore]] è impostata sul valore della stringa. Vedi 15.5 per una descrizione degli oggetti String.

Come tecnica specifica, questo è un trucco per spiegare come le stringhe possono sembrare avere metodi anche se non sono realmente oggetti.

A parte questo, gli oggetti wrapper non sono molto utili. Non so perché sono nella lingua. Preferirei che non lo fossero. 🙂