Все объекты можно условно разделить на несколько видов:
- глобальный объект;
- объектные типы:
- объекты-обертки.
Все примитивы в JavaScript (например, Number, String, Boolean и т.д.) не имеют свойств. Примитивный тип данных является простым строительным блоком языка. По сути, это значение, и как таковое оно не имеет свойств.
Однако рассмотрим следующий код:
1 2 |
let str = "привет"; console.log(str.toUpperCase()); // ПРИВЕТ |
Похоже, что str явно имеет свойство toUpperCase . Но если строки - примитивы и не являются объектами, то почему они имеют такие свойства, например, как toUpperCase, toLowerCase и т. д.?
Всякий раз, когда мы пытаемся получить доступ к свойству строки str, JavaScript приводит значение строки к объекту с помощью конструктора new String(str). Этот объект называется объектом-оберткой. Он наследует все методы объекта String (посмотреть которые можно через console.dir(String); ) и используется для разрешения ссылки на свойство глобального объекта String. После разрешения вызванного свойства объект-оболочка отбрасывается. Эта же концепция применима к числам (number) и логическим значениям (boolean).
По указанной выше причине следующий фрагмент кода вернет undefined:
1 2 3 |
let str = "привет"; str.custom = 1; console.log (str.custom); // undefined |
- Строка 1. Инициализируется переменная str = 'привет';
- Строка 2. JavaScript создает объект-оболочку String, устанавливает его пользовательское свойство custom = 1, а затем отбрасывает его. По сути, он работает примерно так:
1234let str = 'привет';var temp = new String (str); // объект-оберткаtemp.custom = 1;// конец строки для tempЕсли вывести temp в Firebug, Chrome Developer Toolbar или любом другом инструменте отладки, то увидим что-то вроде:
123456789console.log (temp); // String// 0: "п" // 1: "р"// 2: "и"// 3: "в"// 4: "е"// 5: "т"// custom: 1// length: 6Как можно видеть, настраиваемое свойство устанавливается для временного объекта-оболочки.
- Строка 3. console.log (str.custom); JavaScript создает объект String - обертку для исходного строкового значения, а затем пытается прочитать custom - свойство, которое не существует. Возвращается результат undefined. Объект-оболочка снова отбрасывается.
Обычно объекты-обертки можно рассматривать просто как особенность реализации JavaScript: достаточно знать, что строки, числа и логические значения отличаются от объектов тем, что их свойства доступны только для чтения и что вы не можете определять для них новые свойства (см. пример выше).
Cуществует возможность (но в этом почти никогда нет необходимости или смысла) явно создавать объекты-обертки вызовом конструктора String(), Number() или Boolean():
1 2 3 4 |
var s = "test", n = 1, b = true; // Строка, число и логическое значение, var S = new String(s); // Объект String var N = new Number(n); // Объект Number var В = new Boolean(b); // Объект Boolean |
При необходимости интерпретатор JavaScript обычно автоматически преобразует объекты-обертки, т. е. объекты S, N и В в примере выше, в обертываемые ими простые значения примитивов, но они не всегда ведут себя точно так же, как значения s, n и b:
- нестрогое равенство == будет обрабатывать примитив и его объект-оболочку как равные;
- строгое равенство === будет рассматривать примитив и его объект-оболочку как разные объекты.
Примеры для string и number:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var x = "привет"; // примитив var y = new String("привет"); // объект-обертка console.log(typeof x); // string console.log(typeof y); // object x == y; // true x === y; // false // Тот же принцип применим к числам. var m = 1; var n = new String(1); console.log(typeof m); // number console.log(typeof n); // object m == n; // true m === n; // false |
Однако когда дело доходит до number, JavaScript дает вам больше свободы: вы можете создавать свои собственные объекты number, и позволить приведению типа разрешить любую числовую операцию за вас. Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var x = { num: 2, valueOf: function() { return this.num * 2; } }; var y = { num: 3, valueOf: function() { return this.num * 2; } }; console.log(x + y); // 10 |
Как видно из приведенного выше кода, сложение привело объекты x и y к примитивным значениям. JavaScript знает каково примитивное значение моего числового объекта, потому что он ищет и выполняет метод valueOf. Пока этот метод есть в созданном вами объекте (и предполагается, что он возвращает число), ваш объект может быть математически обработан (хотя, вы должны быть предупреждены, у объекта Number, конечно, есть больше методов, чем просто valueOf , например toExponential , toFixed , toLocaleString , toPrecision и toString ).
См. также Преобразование типов в JavaScript
Помните, что вызов конструктора Number без оператора new пытается преобразовать значение в его примитивное представление. То же самое касается String и Boolean.
Значения null и undefined не имеют объектов-оберток: любые попытки обратиться к свойствам этих значений будет вызывать ошибку ТуреError.