146 votes

Quelle est la différence entre les littéraux de chaîne et de la Chaîne des objets en JavaScript?

Prises de MDN

Les littéraux de chaîne (notée par simple ou double quotes) et les chaînes de caractères retourné à partir de la Chaîne des appels à la non-constructeur contexte (c'est à dire, sans en utilisant le nouveau mot-clé) sont primitives des chaînes de caractères. JavaScript automatiquement convertit des primitives pour les objets de Chaîne, de sorte qu'il est possible d'utiliser Chaîne de méthodes de l'objet pour des primitifs cordes. Dans les contextes où un la méthode est invoquée sur une primitive de chaîne ou d'une recherche de propriété se produit, JavaScript, automatiquement automatiquement la chaîne de caractères primitifs et l'appel à la méthode ou à exécuter la recherche de propriété.

Alors, j'ai pensé (logiquement) les opérations (les appels de méthode) sur les littéraux de chaîne doit être plus lent que les opérations sur les Objets string parce que toute chaîne de caractères littérale est converti en chaîne de caractères de l'Objet (travail supplémentaire) avant l' method appliqué sur la chaîne.

Mais dans ce cas de test, le résultat est à l'opposé. Le bloc de code-1 court plus vite que le bloc de code-2, les deux blocs de code sont donnés ci-dessous:

bloc de code-1 :

var s = '0123456789';
for (var i = 0; i < s.length; i++) {
  s.charAt(i);
}

bloc de code-2 :

var s = new String('0123456789');
for (var i = 0; i < s.length; i++) {
    s.charAt(i);
}

Les résultats varient selon les navigateurs, mais le bloc de code-1 est toujours plus rapide. Quelqu'un peut-il m'expliquer pourquoi, pourquoi le bloc de code-1 est plus rapide que le bloc de code-2.

181voto

flavian Points 11275

JavaScript a deux principales catégories de type de, primivites et des objets.

var s = 'test';
var ss = new String('test');

La citation simple/double citer les modèles sont identiques en termes de fonctionnalités. Cela mis à part, le comportement que vous essayez de nom est appelé auto-boxing. Donc ce qui se passe réellement est qu'une primitive est converti son emballage type de méthode de l'emballage type est invoquée. Mettre simple:

var s = 'test';

Est un type de données primitif. Il n'a pas de méthodes, il n'est rien de plus qu'un pointeur à un raw de la mémoire des données de référence, ce qui explique l'accélération de l'accès aléatoire de la vitesse.

Donc ce qui arrive quand vous ne s.charAt(i) par exemple?

Depuis s n'est pas une instance d' String, JavaScript, auto-box squi a typeof string de son emballage type, String, avec typeof object ou plus précisément s.valueOf(s).prototype.toString.call = [object String].

L'auto-boxing comportement jette s d'avant en arrière pour son emballage de type en tant que de besoin, mais la norme opérations sont incroyablement rapides car vous avez affaire à un simple type de données. Toutefois auto-boxing et Object.prototype.valueOf ont des effets différents.

Si vous voulez forcer l'auto-boxing ou de jeter une primitive de son emballage, vous pouvez utiliser Object.prototype.valueOf, mais le comportement est différent. Basé sur une grande variété de scénarios de test, auto-boxing ne s'applique que le "nécessaire" des méthodes, sans altérer la primitive de la nature de la variable. C'est pourquoi vous obtenez une meilleure vitesse.

38voto

Fabrício Matté Points 26309

C'est plutôt dépendant de l'implémentation, mais je vais prendre un coup. Je vais illustrer avec des V8 mais je suppose que d'autres interprètes de recourir à des approches similaires.

Une primitive de chaîne est analysée à un v8::String objet. Par conséquent, les méthodes peuvent être invoquées directement sur elle, comme mentionné par @jfriend00.

Un objet de type String, dans l'autre main, est analysé à un v8::StringObject qui s'étend Object et, en plus d'être à part entière un objet, servir comme un wrapper pour v8::String.

Maintenant, il est seulement logique, un appel à l' new String('').method() a pour unbox cette v8::StringObjects' v8::String avant l'exécution de la méthode, il est donc plus lent.


Dans la plupart des autres langues, des valeurs primitives n'ont pas de méthodes.

Le chemin du MDN met il semble être le moyen le plus simple pour expliquer comment des primitives' auto-boxing œuvres (comme mentionné dans d' @flav's réponse), qui est, comment JavaScript est primitive-y les valeurs peuvent appeler des méthodes.

Cependant, un interprète intelligente ne sera pas convertir une chaîne de caractères primitifs-y pour objet de Chaîne chaque fois que vous devez à appeler une méthode, évidemment.

À un niveau très faible, les Chaînes sont le plus souvent mis en œuvre comme immuable de valeurs scalaires. Exemple wrapper de la structure:

StringObject > String (> ...) > char[]

Le plus loin vous êtes à partir de la primitive, plus il faudra de temps pour l'obtenir. Dans la pratique, String primitives sont beaucoup plus fréquents que l' StringObjects, il n'est donc pas une surprise pour les interprètes d'ajouter des méthodes à la Chaîne primitives correspondantes (interprété) des objets de la Classe au lieu de la conversion en arrière et en avant entre String et StringObject comme MDN explication suggère.

15voto

Chaîne de caractères Littérale vs Objet String

Un Littéral de chaîne: Chaîne de caractères littéraux sont immuables, ce qui signifie que, une fois qu'ils ont créé leur état ne peut pas être changé , ce qui les rend également thread-safe.

var a = 's'; var b = 's';

a==b résultat sera le "vrai" à la fois de la chaîne de consulter du même objet

Chaîne De L'Objet:

Ici deux objets différents sont créés et ils ont des références différentes:

var a= new String("s"); var b= new String("s");

a==b résultat sera faux , parce qu'ils ont des références différentes.

Cheerios !!

12voto

Paul S. Points 20115

Si vous utilisez new, vous êtes en indiquant explicitement que vous souhaitez créer une instance d'un Objet. Par conséquent, new String est la production d'un Objet habillage de la Chaîne primitive, ce qui signifie que toute action sur il s'agit d'une couche supplémentaire de travail.

typeof new String(); // "object"
typeof '';           // "string"

Comme elles sont de différents types, votre JavaScript interprète peut également optimiser différemment, comme mentionné dans les commentaires.

7voto

jfriend00 Points 152127

Lorsque vous déclarez:

var s = '0123456789';

vous créez une chaîne de caractères primitifs. Cette chaîne primitive a des méthodes qui vous permettent d'appeler des méthodes sur elle sans la conversion de la primitive d'une première classe de l'objet. Si votre supposition que ce serait plus lent parce que la chaîne doit être converti en un objet n'est pas correct. Il n'a pas à être converti en un objet. La primitive elle-même pouvez appeler les méthodes.

La conversion à une part entière de l'objet (qui permet d'ajouter de nouvelles propriétés) est une étape supplémentaire et de ne pas faire la chaîne oeprations plus vite (en fait votre test montre que cela les rend plus lent).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X