Как строка Javascript не является объектом?
Это не настройка для шутки, я действительно спрашиваю.
Дуглас Крокфорд любит говорить, что в прототипном объектно-ориентированном языке javascript нет необходимости в new
.
Он объясняет, что new
был просто добавлен, чтобы дать людям, исходящим из класса (на основе классического) объектно-ориентированного программирования, некоторый уровень комфорта:
JavaScript - это прототипный язык, но он имеет оператор new
, который пытается сделать его похожим на классический язык. Это, как правило, путает программистов, что приводит к некоторым проблемным шаблонам программирования.
Вам не нужно использовать new Object()
в JavaScript. Вместо этого используйте литерал объекта {}
.
Хорошо, отлично:
Но затем комментатор 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