Как строка Javascript не является объектом?

Это не настройка для шутки, я действительно спрашиваю.

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

Он объясняет, что new был просто добавлен, чтобы дать людям, исходящим из класса (на основе классического) объектно-ориентированного программирования, некоторый уровень комфорта:

JavaScript, We Hardly new Я

JavaScript - это прототипный язык, но он имеет оператор new, который пытается сделать его похожим на классический язык. Это, как правило, путает программистов, что приводит к некоторым проблемным шаблонам программирования.

Вам не нужно использовать new Object() в JavaScript. Вместо этого используйте литерал объекта {}.

Хорошо, отлично:

  • new bad
  • {} good

Но затем комментатор Vítor De Araújo отметил, что эти два не совпадают. Он приводит пример, показывающий, что string не похож на object:

Строковый объект и строковое значение - это не одно и то же:

js> p = "Foo"
Foo
js> p.weight = 42
42
js> p.weight // Returns undefined

js> q = new String("Foo")
Foo
js> q.weight = 42
42
js> q.weight
42

Строковое значение не может иметь новых свойств. То же самое справедливо и для других типов.

Что здесь происходит, если string не является object? Я запутываю javascript с некоторыми другими языками, где все является объектом?

Ответ 1

"Все является объектом"... это одно из больших заблуждений, которые существуют по всему языку.

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

Это правда, строка является примитивным значением, но вы можете получить доступ ко всем методам, унаследованным от String.prototype, как если бы это был объект.

Свойство операторы доступа (точка и обозначение в скобках) временно преобразуют строковое значение в объект String, чтобы иметь возможность доступа к этим методам, например:

"ab".charAt(1); // "b"

То, что происходит за кулисами, выглядит примерно так:

new String("ab").charAt(1); // "b", temporal conversion ToObject

Как и в других примитивных значениях, таких как Boolean и Number, существуют обертки объектов, которые являются просто объектами, содержащими примитивное значение, как в вашем примере:

var strObj = new String("");
strObj.prop = "foo";

typeof strObj; // "object"
typeof strObj.prop; // "string"

Пока с примитивом:

var strValue = "";
strValue.prop = "foo";

typeof strValue; // "string"
typeof strValue.prop; // "undefined"

И это происходит потому, что средство доступа к свойствам во второй строке выше создает новый временный объект, как:

var strValue = "";
new String(strValue).prop = "foo"; // a new object which is discarded
//...

Ответ 2

Самое важное различие между строкой и объектом заключается в том, что объекты должны следовать этому правилу для оператора ==:

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

Таким образом, в то время как строки имеют удобный == который сравнивает значение, вам не повезло, когда любой другой неизменный тип объекта ведет себя как тип значения. (Могут быть и другие отличия, но это единственное, что ежедневно вызывает восторг разработчиков JavaScript). Примеры:

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