String object versus literal – modification du prototype?

Je me demande pourquoi il semble que l'ajout d'une méthode au prototype d'un littéral de chaîne semble fonctionner, mais l'ajout d'une propriété ne fonctionne pas? Je jouais avec des idées en rapport avec cette question et j'avais le code suivant:

String.prototype._str_index1 = 0; String.prototype._str_reset = function() { this._str_index1 = 0; }; String.prototype._str_substr = function(len) { var ret = this.substr(this._str_index1, len); this._str_index1 = this._str_index1 + len; return ret; }; var testString = new String('Loremipsumdolorsitamet,consectetur'); log(testString._str_substr(5)); log(testString._str_substr(4)); ​ 

Cela fonctionne bien. Si toutefois je change la troisième dernière ligne vers:

 var testString = 'Loremipsumdolorsitamet,consectetur'; 

… il semble que, bien que la méthode _str_substr existe et soit appelable sur le _str_substr chaîne, la valeur de la propriété _str_index1 est toujours 0.

Quoi de neuf?

La primitive de chaîne est convertie en objet String transitoire chaque fois que vous essayez d'invoquer une méthode de l'objet String (le moteur JavaScript convertit en interne une primitive de chaîne à un objet String si nécessaire). Une fois cette fonction renvoyée, l'objet String (converti discrètement) est retourné à une primitive de chaîne (sous le capot) et cette nouvelle primitive est renvoyée (et la plupart du temps assignée à une variable); Chaque fois qu'une méthode de l'objet String est invoquée .

Ainsi, après chaque invocation de testString._str_substr , _str_index1 est jeté avec l'objet et un nouvel objet (avec une réinitialisation _str_index1 ) est créé lorsque _str_substr est appelé à nouveau.

Voir aussi MDC :

Parce que JavaScript convertit automatiquement entre les primitives de chaîne et les objets String, vous pouvez appeler l'une des méthodes de l'objet String sur une primitive de chaîne. JavaScript convertit automatiquement la primitive de chaîne en un objet String temporaire, appelle la méthode puis supprime l'objet String temporaire.

Cela se produit parce que l'objet est créé et immédiatement jeté lorsque l'affectation est effectuée, car c'est un littéral de chaîne.

Donc, avec la première version, un objet est créé et maintenu, donc testString est un objet, pas un littéral de chaîne. Dans le second cas, un objet est créé et jeté, donc toutes les propriétés se perdent …

Essayez maintenant de remplacer cette ligne par ceci:

 var testString = 'Loremipsumdolorsitamet,consectetur'._str_substr(); 

Intéressant, n'est-ce pas? Il renvoie toujours une primitive de chaîne, mais cela peut être corrigé …

 String.prototype._str_substr = function(len) { var ret = this.substr(this._str_index1, len); this._str_index1 = this._str_index1 + len; return new String(ret); }; 

Bien sûr, ce ne sont que des suggestions conçues pour aider à expliquer pourquoi les littératures agissent différemment que les objets, pas les recommandations du monde réel …