edit
This commit is contained in:
parent
e78e527866
commit
05a93ced80
212 changed files with 3213 additions and 3968 deletions
|
@ -1,13 +1,14 @@
|
|||
importance: 3
|
||||
|
||||
---
|
||||
|
||||
# Первый объект
|
||||
|
||||
[importance 3]
|
||||
|
||||
Мини-задача на синтаксис объектов. Напишите код, по строке на каждое действие.
|
||||
<ol>
|
||||
<li>Создайте пустой объект `user`.</li>
|
||||
<li>Добавьте свойство `name` со значением `Вася`.</li>
|
||||
<li>Добавьте свойство `surname` со значением `Петров`.</li>
|
||||
<li>Поменяйте значение `name` на `Сергей`.</li>
|
||||
<li>Удалите свойство `name` из объекта.</li>
|
||||
</ol>
|
||||
|
||||
1. Создайте пустой объект `user`.
|
||||
2. Добавьте свойство `name` со значением `Вася`.
|
||||
3. Добавьте свойство `surname` со значением `Петров`.
|
||||
4. Поменяйте значение `name` на `Сергей`.
|
||||
5. Удалите свойство `name` из объекта.
|
||||
|
||||
|
|
|
@ -2,22 +2,23 @@
|
|||
|
||||
Объекты в JavaScript сочетают в себе два важных функционала.
|
||||
|
||||
Первый -- это ассоциативный массив: структура, пригодная для хранения любых данных. В этой главе мы рассмотрим использование объектов именно как массивов.
|
||||
Первый -- это ассоциативный массив: структура, пригодная для хранения любых данных. В этой главе мы рассмотрим использование объектов именно как массивов.
|
||||
|
||||
Второй -- языковые возможности для объектно-ориентированного программирования. Эти возможности мы изучим в последующих разделах учебника.
|
||||
|
||||
[cut]
|
||||
|
||||
## Ассоциативные массивы
|
||||
|
||||
[Ассоциативный массив](http://ru.wikipedia.org/wiki/%D0%90%D1%81%D1%81%D0%BE%D1%86%D0%B8%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B0%D1%81%D1%81%D0%B8%D0%B2) -- структура данных, в которой можно хранить любые данные в формате ключ-значение.
|
||||
[Ассоциативный массив](http://ru.wikipedia.org/wiki/%D0%90%D1%81%D1%81%D0%BE%D1%86%D0%B8%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B0%D1%81%D1%81%D0%B8%D0%B2) -- структура данных, в которой можно хранить любые данные в формате ключ-значение.
|
||||
|
||||
Её можно легко представить как шкаф с подписанными ящиками. Все данные хранятся в ящичках. По имени можно легко найти ящик и взять то значение, которое в нём лежит.
|
||||
|
||||
<img src="object.png">
|
||||

|
||||
|
||||
В отличие от реальных шкафов, в ассоциативный массив можно в любой момент добавить новые именованные "ящики" или удалить существующие. Далее мы увидим примеры, как это делается.
|
||||
|
||||
Кстати, в других языках программирования такую структуру данных также называют *"словарь"* и *"хэш"*.
|
||||
Кстати, в других языках программирования такую структуру данных также называют *"словарь"* и *"хэш"*.
|
||||
|
||||
## Создание объектов
|
||||
|
||||
|
@ -40,22 +41,21 @@
|
|||
var person = {}; // пока пустой
|
||||
```
|
||||
|
||||
<img src="object-person-empty.png">
|
||||
|
||||

|
||||
|
||||
Основные операции с объектами -- это создание, получение и удаление свойств.
|
||||
|
||||
Для обращения к свойствам используется запись "через точку", вида `объект.свойство`, например:
|
||||
|
||||
```js
|
||||
// при присвоении свойства в объекте автоматически создаётся "ящик"
|
||||
// при присвоении свойства в объекте автоматически создаётся "ящик"
|
||||
// с именем "name" и в него записывается содержимое 'Вася'
|
||||
person.name = 'Вася';
|
||||
|
||||
person.age = 25; // запишем ещё одно свойство: с именем 'age' и значением 25
|
||||
```
|
||||
|
||||
<img src="object-person-1.png">
|
||||

|
||||
|
||||
Значения хранятся "внутри" ящиков. Обратим внимание -- любые значения, любых типов: число, строка -- не важно.
|
||||
|
||||
|
@ -72,14 +72,14 @@ delete person.age;
|
|||
|
||||
Осталось только свойство `name`:
|
||||
|
||||
<img src="object-person-2.png">
|
||||

|
||||
|
||||
Следующая операция:
|
||||
<ol start="4">
|
||||
<li>**Проверка существования свойства с определенным ключом.**</li>
|
||||
</ol>
|
||||
|
||||
Для проверки существования свойства в объекте есть оператор `in`.
|
||||
Для проверки существования свойства в объекте есть оператор `in`.
|
||||
|
||||
Его синтаксис: `"prop" in obj`, причем имя свойства -- в виде строки, например:
|
||||
|
||||
|
@ -95,8 +95,7 @@ if ("name" in person) {
|
|||
|
||||
Но если свойство не существует, то вернется специальное значение `undefined`:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
```js run
|
||||
var person = {};
|
||||
|
||||
alert( person.lalala ); // undefined, нет свойства с ключом lalala
|
||||
|
@ -104,8 +103,7 @@ alert( person.lalala ); // undefined, нет свойства с ключом la
|
|||
|
||||
Таким образом **мы можем легко проверить существование свойства -- получив его и сравнив с `undefined`**:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
```js run
|
||||
var person = {
|
||||
name: "Василий"
|
||||
};
|
||||
|
@ -114,16 +112,14 @@ alert( person.lalala === undefined ); // true, свойства нет
|
|||
alert( person.name === undefined ); // false, свойство есть.
|
||||
```
|
||||
|
||||
[smart header="Разница между проверками `in` и `=== undefined`"]
|
||||
|
||||
````smart header="Разница между проверками `in` и `=== undefined`"
|
||||
Есть два средства для проверки наличия свойства в объекте: первое -- оператор `in`, второе -- получить его и сравнить его с `undefined`.
|
||||
|
||||
Они почти идентичны, но есть одна небольшая разница.
|
||||
|
||||
Дело в том, что технически возможно, что *свойство есть и равно `undefined`*:
|
||||
|
||||
```js
|
||||
//+ untrusted refresh run
|
||||
```js untrusted refresh run
|
||||
var obj = {};
|
||||
obj.test = undefined; // добавили свойство со значением undefined
|
||||
|
||||
|
@ -138,26 +134,24 @@ alert( obj.blabla === undefined ); // true
|
|||
|
||||
Но оператор `in` гарантирует правильный результат:
|
||||
|
||||
```js
|
||||
//+ untrusted refresh run
|
||||
```js untrusted refresh run
|
||||
var obj = {};
|
||||
obj.test = undefined;
|
||||
|
||||
*!*
|
||||
alert( "test" in obj ); // true
|
||||
alert( "test" in obj ); // true
|
||||
alert( "blabla" in obj ); // false
|
||||
*/!*
|
||||
```
|
||||
|
||||
Как правило, в коде мы не будем присваивать `undefined`, чтобы корректно работали обе проверки. А в качестве значения, обозначающего неизвестность и неопределенность, будем использовать `null`.
|
||||
[/smart]
|
||||
|
||||
````
|
||||
|
||||
### Доступ через квадратные скобки
|
||||
|
||||
Существует альтернативный синтаксис работы со свойствами, использующий квадратные скобки `объект['свойство']`:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
```js run
|
||||
var person = {};
|
||||
|
||||
person['name'] = 'Вася'; // то же что и person.name = 'Вася'
|
||||
|
@ -165,8 +159,7 @@ person['name'] = 'Вася'; // то же что и person.name = 'Вася'
|
|||
|
||||
Записи `person['name']` и `person.name` идентичны, но квадратные скобки позволяют использовать в качестве имени свойства любую строку:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
```js run
|
||||
var person = {};
|
||||
|
||||
person['любимый стиль музыки'] = 'Джаз'; // то же что и person.name = 'Вася'
|
||||
|
@ -174,8 +167,7 @@ person['любимый стиль музыки'] = 'Джаз'; // то же чт
|
|||
|
||||
Такое присвоение было бы невозможно "через точку", так интерпретатор после первого пробела подумает, что свойство закончилось, и далее выдаст ошибку:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
```js run
|
||||
person.любимый стиль музыки = 'Джаз'; // ??? ошибка
|
||||
```
|
||||
|
||||
|
@ -185,8 +177,7 @@ person.любимый стиль музыки = 'Джаз'; // ??? ошибка
|
|||
|
||||
Квадратные скобки также позволяют обратиться к свойству, имя которого хранится в переменной:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
```js run
|
||||
var person = {
|
||||
age: 25
|
||||
};
|
||||
|
@ -199,7 +190,7 @@ alert( person[key] ); // выведет person['age']
|
|||
|
||||
Доступ через точку используется, если мы на этапе написания программы уже знаем название свойства. А если оно будет определено по ходу выполнения, например, введено посетителем и записано в переменную, то единственный выбор -- квадратные скобки.
|
||||
|
||||
### Объявление со свойствами
|
||||
### Объявление со свойствами
|
||||
|
||||
Объект можно заполнить значениями при создании, указав их в фигурных скобках: `{ ключ1: значение1, ключ2: значение2, ... }`.
|
||||
|
||||
|
@ -254,12 +245,12 @@ alert(user.name) // "Таня"
|
|||
alert(user.size.top) // 90
|
||||
```
|
||||
|
||||
Здесь значением свойства `size` является объект `{top: 90, middle: 60, bottom: 90 }`.
|
||||
Здесь значением свойства `size` является объект `{top: 90, middle: 60, bottom: 90 }`.
|
||||
## Компактное представление объектов
|
||||
|
||||
[warn header="Hardcore coders only"]
|
||||
```warn header="Hardcore coders only"
|
||||
Эта секция относится ко внутреннему устройству структуры данных. Она не обязательна к прочтению.
|
||||
[/warn]
|
||||
```
|
||||
|
||||
Браузер использует специальное "компактное" представление объектов, чтобы сэкономить память в том случае, когда однотипных объектов много.
|
||||
|
||||
|
@ -272,7 +263,7 @@ var user = {
|
|||
};
|
||||
```
|
||||
|
||||
Здесь содержится информация о свойстве `name` и его строковом значении, а также о свойстве `age` и его численном значении. Представим, что таких объектов много.
|
||||
Здесь содержится информация о свойстве `name` и его строковом значении, а также о свойстве `age` и его численном значении. Представим, что таких объектов много.
|
||||
|
||||
Получится, что информация об именах свойств `name` и `age` дублируется в каждом объекте. Чтобы этого избежать, браузер применяет оптимизацию.
|
||||
|
||||
|
@ -280,8 +271,7 @@ var user = {
|
|||
|
||||
Например, есть много объектов с полями `name` и `age`:
|
||||
|
||||
```js
|
||||
//+ no-beautify
|
||||
```js no-beautify
|
||||
{name: "Вася", age: 25}
|
||||
{name: "Петя", age: 22}
|
||||
{name: "Маша", age: 19}
|
||||
|
@ -290,8 +280,7 @@ var user = {
|
|||
|
||||
Для их эффективного хранения будет создана структура, которая описывает данный вид объектов. Выглядеть она будет примерно так: `<string name, number age>`. А сами объекты будут представлены в памяти только данными:
|
||||
|
||||
```js
|
||||
//+ no-beautify
|
||||
```js no-beautify
|
||||
<структура: string name, number age>
|
||||
Вася 25
|
||||
Петя 22
|
||||
|
@ -306,34 +295,27 @@ var user = {
|
|||
user.isAdmin = true;
|
||||
```
|
||||
|
||||
В этом случае браузер смотрит, есть ли уже структура, под которую подходит такой объект. Если нет -- она создаётся и объект привязывается к ней.
|
||||
|
||||
В этом случае браузер смотрит, есть ли уже структура, под которую подходит такой объект. Если нет -- она создаётся и объект привязывается к ней.
|
||||
|
||||
**Эта оптимизация является примером того, что далеко не всё то, что мы пишем, один-в-один переносится в память.**
|
||||
|
||||
Современные интерпретаторы очень стараются оптимизировать как код, так и структуры данных. Детали применения и реализации этого способа хранения варьируются от браузера к браузеру. О том, как это сделано в Chrome можно узнать, например, из презентации [Know Your Engines](http://www.slideshare.net/newmovie/know-yourengines-velocity2011). Она была некоторое время назад, но с тех пор мало что изменилось.
|
||||
|
||||
|
||||
## Итого
|
||||
|
||||
Объекты -- это ассоциативные массивы с дополнительными возможностями:
|
||||
|
||||
- Доступ к элементам осуществляется:
|
||||
<ul>
|
||||
<li>Доступ к элементам осуществляется:
|
||||
<ul>
|
||||
<li>Напрямую по ключу `obj.prop = 5`</li>
|
||||
<li>Через переменную, в которой хранится ключ:
|
||||
<li>Напрямую по ключу `obj.prop = 5`
|
||||
- Через переменную, в которой хранится ключ:
|
||||
|
||||
```js
|
||||
var key = "prop";
|
||||
obj[key] = 5
|
||||
```
|
||||
```js
|
||||
var key = "prop";
|
||||
obj[key] = 5
|
||||
```
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
<li>Удаление ключей: `delete obj.name`.</li>
|
||||
<li>Существование свойства может проверять оператор `in`: `if ("prop" in obj)`, как правило, работает и просто сравнение `if (obj.prop !== undefined)`.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue