Объекты
Содержание
- Определение объекта
- Синтаксис создания объекта.
- Свойства и методы объекта
- Создание, изменение и удаление свойства
- Доступ к свойству
- Дублирование и клонирование
- Проверка наличия свойства в объекте
- https://habrahabr.ru/post/119391/ - подробнее о конструктор-функции и "подводных камнях" ее использования
- http://jsraccoon.ru/oop-constructors - oop-constructor
- https://habrahabr.ru/post/151070/ - Функции-конструкторы — как объекты,(prototype). Объекты,(__proto__). constructor, ={}, как функция-конструктор new Object() *
Определение объекта
Объект в JavaScript — это составной тип данных, который может хранить в себе числа, строки, булевые типы данных и т.д. Также объекты могут хранить в себе функции и другие объекты.
В JavaScript всё !!! ведет !!! себя, как объект, лишь за двумя исключениями —
null
иundefined
.
Объекты в JavaScript сочетают в себе два важных функционала.
Первый – это ассоциативный массив: структура, пригодная для хранения любых данных.
Второй – языковые возможности для объектно-ориентированного программирования.
Ассоциативный массив – структура данных, в которой можно хранить любые данные в формате ключ-значение.
Синтаксис создания объекта.
// 1 - конструктор-функция
obj1 = new Object();
// 2 - литеральная нотация
obj2 = {};
Конструктор-функция
Конструктором становится любая функция, вызванная через new
.
Технически, любая функция может быть использована как конструктор. То есть, любую функцию можно вызвать при помощи new
. Как-то особым образом указывать, что она – конструктор – не надо.
Но, чтобы выделить функции, задуманные как конструкторы, их называют с большой буквы: Person
, а не person
.
function Person(name) {
this.name = name;
this.canRelocate = true;
}
var person = new Person('Stiv');
//result
person;
Object { name: "Stiv", canRelocate: true }
!!! Подробнее конструктор будет рассмотрен в соостветствующей статье.(готовится)
Литеральная нотация
В литеральной нотации объект описывается внутри блока фигурных скобок {}
, как набор разделенных запятой пар ключ/значение.
Ключи объекта могут быть как строками, так и идентификаторами.
После имени ставится двоеточие.
var person = {
"name" : 'Stiv',
"age" : 31,
"Search job" : false
};
// result
person;
Object { name: "Stiv", age: 31, "Search job": false }
В объекте не должно стоять запятой после последней пары ключ/значение, так как это может привести к ошибкам.
Литерал объекта не требует использования оператора
new
для создания экземпляра, но он не должен стоять в начале выражения, так как открытая{
может быть воспринята как начало блока.Новый объект наследуется(готовится) от
Object.prototype
и не имеет собственных свойств. (готовится)
Свойства и методы. Создание, изменение и удаление свойства
В JavaScript всё !!! ведет !!! себя, как объект, лишь за двумя исключениями —
null
иundefined
.
***
Если значения представляют собой базовые типы или другие объекты, их называют свойствами.
Если же это функции, их называют методами объекта.
//создаем пустой объект
var car = {};
//добавляем свойство:
car.name = "Ford";
//или метод:
car.getName = function() {
return car.name;
};
Создание свойства
Новые свойства объекта могут быть добавлены с помощью конструкций
car.color = 'green';
car.key3 = 33;
car["string key"] = "string";
При присвоении свойства в объекте автоматически создаётся ключ с указанным именем и в него записывается соответствующее значение.
Изменение свойства
// вводим
car.name; // получаем "Ford"
// набираем
car.name = "Audi";
car.name; // получаем "Audi"
Доступ к свойствам ( .точечная vs квадратные скобки ["key"] )
Получить доступ к свойствам объекта можно двумя способами: используя либо точечную нотацию, либо запись квадратными скобками.
var car = { year: '2002' }
car.year; // 2002
car['year']; // 2002
var get = 'year';
foo[get]; // 2002
car.1234; // SyntaxError
car['1234']; // работает
Обе нотации идентичны по принципу работы — одна лишь разница в том, что использование квадратных скобок позволяет устанавливать свойства динамически и использовать такие имена свойств, какие в других случаях могли бы привести к синтаксической ошибке.
Доступ к свойству через переменную
Квадратные скобки также позволяют обратиться к свойству, имя которого хранится в переменной
var key1 = 'color';
car[key1];
Удаление свойства
Единственный способ удалить свойство у объекта — использовать оператор delete
.
Устанавливая свойство в undefined
или null
, мы только заменяете связанное с ним значение, но не удаляем ключ.
delete car.key3;
delete car["string key"];
Если ссылок на значение больше нет, то сборщиком мусора удаляется и само значение, но ключ объекта при этом всё так же имеет новое значение.
var obj = {
bar: 1,
foo: 2,
baz: 3
};
obj.bar = undefined;
obj.foo = null;
delete obj.baz;
for(var i in obj) {
if (obj.hasOwnProperty(i)) {
console.log(i, '' + obj[i]);
}
}
Приведённый код выведет две строки: bar undefined и foo null
— на самом деле удалено было только свойство baz
и посему только оно будет отсутствовать в выводе.
Присвоение объектов
var carDouble = car;
console.log(carDouble + car);
carDouble
по сути всего лишь новая переменная со ссылкой на существующие в car
свойства.
Поэтому изменение происходит в одном месте но ссылки к этому месту могут быть различны
carDouble.name = 'Honda';
carDouble.name; //'Honda'
car.name; // 'Honda'
Чтобы избежать подобного в случае необходимости, нужно не присваивать, а клонировать объект.
Клонирование объектов
var carClone = {}; // Create new empty object
carClone;
//
for (var k in car){
carClone[k] = car[k]; // Create new key in new obj and get keys value from main object
}
carClone;
Особенности и замечания
Числовые литералы в качестве объектов
Неверно считать, что числовые литералы нельзя использовать в качестве объектов — это распространённое заблуждение. Его причиной является упущение в парсере JavaScript, благодаря которому применение точечной нотации к числу воспринимается им как литерал числа с плавающей точкой.
2.toString(); // вызывает SyntaxError
Есть несколько способов обойти этот недостаток и любой из них можно использовать для того,
чтобы работать с числами, как с объектами:
2..toString(); // вторая точка распознаётся корректно
2 .toString(); // обратите внимание на пробел перед точкой
(2).toString(); // двойка вычисляется заранее
Запись ключей
var test = {
'case': 'Я — ключевое слово, поэтому меня надо записывать строкой',
delete: 'Я тоже ключевое слово, так что я' // бросаю SyntaxError
};
Свойства объектов могут записываться как явно символами, так и в виде закавыченных строк.
В связи с другим упущением в парсере JavaScript, этот код выбросит SyntaxError
во всех версиях ранее ECMAScript 5.
Источником ошибки является факт, что delete
— это ключевое слово и поэтому его необходимо записывать как строчный литерал: ради уверенности в том, что оно будет корректно опознано более старыми движками JavaScript.
И еще один пример в пользу строковой нотации, относящийся к JSON:
// валидный JavaScript и валидный JSON
{
"foo": "oof",
"bar": "rab"
}
// валидный JavaScript и НЕвалидный JSON
{
foo: "oof",
bar: "rab"
}
Разница между проверками in и === undefined
Есть два средства для проверки наличия свойства в объекте:
первое – оператор in
,
второе – получить его и сравнить с undefined
.
Они почти идентичны, но есть одна небольшая разница.
Дело в том, что технически возможно, что свойство есть, а его значением является undefined
:
var car = {};
obj.test = undefined; // добавили свойство со значением undefined
// проверим наличие свойств test и заведомо отсутствующего blabla
console.log( car.test === undefined ); // true
console.log( car.tst === undefined ); // true
При этом, как видно из кода, при простом сравнении наличие такого свойства будет неотличимо от его отсутствия.
Но оператор in
гарантирует правильный результат:
console.log( "test" in obj ); // true
console.log( "tst" in obj ); // false
Как правило, в коде мы не будем присваивать
undefined
, чтобы корректно работали обе проверки. А в качестве значения, обозначающего неизвестность и неопределенность, будем использоватьnull
.