Какая разница между строкой примитивы и объекты string в JavaScript?

Взято из МДН

строковые литералы (обозначается двойными или одинарными кавычками) и строки и GT; вернулся из строки вызовов в конструкторе контекста (т. е. без с помощью нового сайта) примитивные строки. JavaScript автоматически преобразование примитивов в объекты string, так что это'ы можно использовать строка объект методы примитивные строки. В контекстах, где метод должен быть вызван на примитивную строку или подстановки собственность В случае JavaScript будет автоматически оборачивать строку примитивные и вызвать метод или выполнить поиск свойств.

Так, я думал, что (логически) операции (вызова метода) и строковые примитивы должны быть медленнее, чем операции со строковыми объектами, потому что любой строки примитивной преобразуется в строковый объект (дополнительные работы) прежде чем "метод" применяется на строку.

Но в этом тест, результат противоположный. В код блок-1 работает быстрее, чем код блока-2, как блоки кода приводятся ниже:

код блок-1 :

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

код блок-2 :

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

Результаты варьируется в браузерах, но код блок-1 всегда быстрее. Может кто-нибудь объяснить, почему этот код блок-1 - это быстрее, чем код блока-2.

Комментарии к вопросу (8)
Решение

В JavaScript есть две основные категории типу, primivites и объектов.

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

Одиночные кавычки моделей/двойные кавычки одинаковы с точки зрения функциональности. Кроме того, поведение вы пытаетесь именем называется Авто-бокс. Так что на самом деле происходит, что примитивный преобразуется в тип обертки для метода типа оболочки вызывается. Поставить простой:

var s = 'test';

Примитивный тип данных. Он не имеет никаких методов, это не более чем указатель на сырые ссылка на память данных, которая объясняет гораздо быстрее скорость произвольного доступа.

Так что же происходит, когда вы делаете ы.используя метод charat(я), например?

С " S " - это не экземпляр строка, код JavaScript автоматически поле в, которое естьtypeof на строку с его типом оболочки, строка, с typeof на объект или точнее ы.метод valueOf(ы).прототип.метод toString.звоните = [строка, объект].

Авто-бокс поведение бросает Ы и обратно, чтобы его тип оболочки по мере необходимости, но стандартные операции невероятно быстро, поскольку вы имеете дело с более простой тип данных. Однако авто-бокс и объект.прототип.метод valueOf` имеют различные эффекты.

Если вы хотите заставить авто-бокс или бросить примитивно для своего типа оболочки, вы можете использовать объект.прототип.метод valueOf, но поведение отличается. На основе различных тестовых сценариев, авто-бокс применяется только 'требуется' методов, не изменяя примитивный характер переменной. Именно поэтому вы получите лучшую скорость.

Комментарии (0)

Это скорее зависит от конкретной реализации, но я'll принимать выстрел. Я'МР примером с V8, но я предполагаю, что другие системы используют похожие подходы.

Строковый примитив анализируется в В8::строка объект. Таким образом, методы могут быть вызваны непосредственно на него, как упомянуто jfriend00.

Строковый объект, в другой руке, анализируется в V8 с::StringObject, которая распространяется как "объект" и, помимо того, что это полноценный объект, служит оболочкой для В8::строка`.

Теперь вполне логично, в новую строку('').способ()должен распаковать это с V8::StringObjectи V8::string в перед выполнением метода, следовательно, он медленнее.

<ч>

Во многих других языках, примитивные значения не имеют методов.

Кстати МДН ставит его, кажется, простейший способ объяснить, как примитивы' авто-бокс работает (о чем также говорится в в'ы ответ), то есть, как код JavaScript'ы первобытно-г значения могут вызывать методы.

Однако, умный двигатель не преобразовать строку первобытно-г в строке объект каждый раз нужно вызвать метод. Это также информативно, упомянутых в аннотированный в ES5 спец. применительно к решению свойства (и "методы" с¹) значений примитивных типов:

Примечание объект, который может быть создан на шаге 1 не доступны вне указанных выше метода. Реализация могла бы выбрать, чтобы избежать фактического создания объекта. [...]

На очень низком уровне, струны чаще всего реализуется как неизменяемые значения скаляра. Пример структуры оболочки:

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

Более далеко вы'вновь из первобытного, тем больше времени потребуется, чтобы добраться до него. На практике, строка примитивов гораздо чаще, чем StringObject, поэтому это не сюрприз для двигателей для добавления методов в строку примитивы' соответствующие (интерпретируется) объектов' класса вместо преобразования взад и вперед между String и `StringObject как МДН'объяснение предполагает.


¹ в JavaScript, и"способ" это просто соглашение об именовании для свойство, которое возвращает значение типа function.

Комментарии (2)

В случае строковый литерал мы не сможем присвоить свойства

var x = "hello" ;
x.y = "world";
console.log(x.y); // this will print undefined

Тогда как в случае объекта String можно присвоить свойства

var x = new String("hello");
x.y = "world";
console.log(x.y); // this will print world
Комментарии (2)

Строковых Литералов:

Строковые литералы являются неизменными, что означает, как только они создаются, их состояние может'т быть изменены, что также делает их потокобезопасными.

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

результат==Б будет 'правда' обе строки см.'ы и тому же объекту.

Объект String:

Здесь создаются два разных объекта, и они имеют разные ссылки:

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

результат==Б будет ложным, потому что они имеют разные ссылки.

Комментарии (2)

Если вы используете новый, Вы'вновь недвусмысленно заявив, что вы хотите создать экземпляр Object. Таким образом, новая строка производит в Object обертывания String примитивно, что означает какие-либо действия влечет за собой дополнительный пласт работы.

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

Как они бывают разных типов, ваш переводчик JavaScript может также оптимизировать их по-разному, как сказано в комментарии.

Комментарии (0)

Когда вы заявляете:

var s = '0123456789';

вы создаете строку примитивно. Эту строку примитивными методами, которые позволяют вызывать методы на нем без конвертации примитивных до первого объекта класса. Так что ваше предположение, что это будет медленнее, потому что строка должна быть преобразована в объект не является правильным. Он не должен быть преобразован в объект. Самой примитивной можете вызывать методы.

Преобразование его в полноценный объект (который позволяет добавлять новые свойства) - это лишний шаг и не сделают строку oeprations быстрее (на самом деле тест показывает, что это делает их медленнее).

Комментарии (15)

Существование объекта имеет мало общего с реальным поведением строку в двигателях с ECMAScript/JavaScript как объем корней будет просто содержать объекты функция для этого. Таким образом, используя метод charat(функция int) в случае строкового литерала будут найдены и казнены.

С реального объекта можно добавить еще один слой, где, используя метод charat(int) метод также выполняется на самом объекте до стандартного поведения в кайф (как и выше). Видимо, есть удивительно большой объем проделанной работы в этом случае.

Кстати, я не'т думаю, что примитивы на самом деле превращается в объекты, но сам скрипт будет просто пометить переменную как тип String и, следовательно, он может найти все функции для его, так это выглядит, как вы ссылаться на объект. Дон'т забыть это во время выполнения скрипта, который работает на иных принципах, чем ОО во время выполнения.

Комментарии (0)

Я вижу, что этот вопрос уже давно решен, есть еще одно тонкое различие между строковые литералы и объекты string, как никто, кажется, не затронули его, я думал, что я'd, просто пишу это для полноты картины.

В принципе еще одно различие между двумя, когда использование eval. ивала('1 + 1') дает 2, а функция eval(новую строку('1 + 1')) дает '1 + 1', так что если определенный блок кода может быть выполнен как 'нормально' или с eval, она может привести к странным результатам

Комментарии (3)

Самая большая разница между строкой примитивно и объект String является то, что объекты должны следовать этому правилу для operator в == ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators):

выражение сравнения объектов является только истина, если операнды ссылка один и тот же объект.

Так, в то время как строковые примитивы имеют удобный==, которая сравнивает значение, вы'вновь повезло, когда дело доходит до принятия каких-либо других неизменяемый тип объекта (в том числе строковый объект), ведут себя как тип значения.

"hello" == "hello"
-> true
new String("hello") == new String("hello") // beware!
-> false

(Другие отметили, что объект String является технически изменяемым, потому что вы можете добавлять свойства к нему. Но это's не ясно, что это's полезный для; строковое значение само по себе является не изменяемым.)

Комментарии (1)