Разница между строкой типа javascript и объектом String?

Я общался со стандартом ECMA-262 (ECMAScript Language Specification, 3-е издание, если это имеет значение для этого), я не нашел разницы между 3-м и 5-м выпуском String Type/String Object).

Есть одна вещь, которая меня озадачивает: разница между строковым типом и строковым объектом. Да, я знаю разницу в том смысле, что String Type представляет собой последовательность из 16-битных единиц UTF-16, а String Object - это встроенный объект с его внутренним свойством Class, установленным в "String", и его внутренним значением Value, значение типа String.

Но, читая спецификацию, тип строки, похоже, не раскрывает никаких методов; то есть это просто значение без каких-либо дополнительных свойств. Возьмите этот код, все в точности как ожидалось:

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

Первый тип - это фактический тип строки, а второй - тип объекта (это объект класса String, но его тип данных - объект). Однако, глядя на это:

"foo".charAt(0);

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

Оба они, похоже, раскрывают одни и те же функции, но нет никаких функций в строковом типе, определенном в стандарте ECMA-262; все функции, которые он предоставляет, относятся к объекту String.prototype(и я не вижу ссылки на то, что String Type магически раскрывает все свойства и функции объекта String.prototype в стандарте ECMA-262). Точно так же значения типа String Type автоматически передаются объекту String с исходным значением типа String в качестве его внутреннего свойства Value?

И если они обрабатываются точно так же (что для всех целей и задач они кажутся), почему есть два разных способа представления строки?

Ответ 1

Строки - это тип значения в JS, поэтому они не могут иметь никаких свойств, связанных с ними, без прототипа и т.д. Любая попытка доступа к свойству на них технически выполняет преобразование JS [[ToObject]] (по существу новая строка).

Легкий способ отличия разницы (в браузере)

a = "foo"
a.b = "bar"
alert("a.b = " + a.b); //Undefined

A = new String("foo");
A.b = "bar";
alert("A.b = " + A.b); // bar

Дополнительно

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

истинно, это справедливо только из-за неявных преобразований типа оператора ==

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

не удастся.

Ответ 2

Он аналогичен разнице между int и Integer в Java.

Согласно стандарту, при попытке вызова метода строки автоматически преобразуются в объекты String. См. ECMA 262-3, раздел 11.2.1; шаг 5 вызывает ToObject (который определен в разделе 9.9).

11.2.1 Аксессоры
[...]
Произведение MemberExpression: MemberExpression [Expression] оценивается следующим образом:

  • Вычислить выражение MemberExpression.
  • Вызов GetValue (Результат (1)).
  • Вычислить выражение.
  • Вызов GetValue (Результат (3)).
  • Вызов ToObject (Результат (2)).
  • Вызов ToString (Результат (4)).
  • Возвращает значение типа Reference, базовым объектом которого является Result (5), а именем свойства которого является Result (6).


9.9 ToObject

Оператор ToObject преобразует свой аргумент в значение типа Object в соответствии со следующей таблицей:
[...]
Создайте новый объект String, для свойства [[value]] установлено значение строка. См. 15.5 для описания объектов String.

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

Кроме того, объекты-обертки не очень полезны. Я не знаю, почему они на этом языке. Я скорее желаю, чтобы они не были.:)