# Ассоциативные массивы, `in`, JSON

Кроме обычных массивов, в которых ключем служит целое число от 0 до `array.length -1`, существуют **ассоциативные массивы**, ключем в котором может быть любой другой
тип данных, который **JS** приводит к строке. В **JavaScript** нет специального типа данных для ассоциативных массивов - вместо этого ассоциативные
массивы представлены объектами (`Object`):


## Создание ассоциативного массива и доступ к полям

```javascript
var person = {
    name: "Ivan",
    surname: "Ivanovv",
    "fatherName": "Petrovich",
}

typeof person
```
Нет разницы, определять ключи *литерально* или через строку (в кавычках `"fatherName"`).

Для обращения к элементам по ключу используются следующие нотации:

```javascript
person.fatherName
person["name"]
```

Обратите внимание, что `person.fatherName` работает так же как и `person["name"]`, несмотря на то, что определены по разному.

Для обращения через ключ в переменной используется нотация с квадратными скобками:
```javascript
var key = "surname";

person[key]
person.key
```

Если просто написать `person.key`, то **JavaScript** будет искать ключ `key` *литерально*, а не по значению переменной `key` ("surname")

Вы можете определить новый элемент массива просто присвоив ему значение:

```javascript
person.age = 98;

person
```

Также можно создавать массив через конструктор Object:
```javascript

var a = new Object();
a.name = "Petr"
a.surname = "Petrov";
a["age"] = 17;
```

Получить ключи ассоциативного массива можно с помощью функции `Object.keys`:
```javascript
Object.keys(person)
```

В качестве значений в ассоциативном массиве могут быть любые типы данных, в том числе и другие ассоциативные массивы:
```javascript
var someTree = {
    tag: "table", //html tag
    nestedTags: [ //вложенные тэги
        {
                    tag: "tr",
                    nestedTags: [
                        {
                            tag: "td",
                            content: "some text",
                        },
                        {
                            tag: "td",
                            content: "some text 2",
                        }
                    ]
        }
    ],
    options: 
    {
        border: 1,
    },
}
```

Нет сложностей с циклическими ссылками:
```javascript
var a = {}
var b = {}
a.b = b
b.a = a

b.b = b
a.a = a

a.name = "A"
b.name = "B"
```

## `in`

Ключевое слово `in` используется для двух задач:
- проверка наличия ключа в ассоциативном массиве

```javascript
"fatherName" in a
"age" in person
```

- конструкция `for (var key in arr)` для перебора всех элементов ассоциативного массива

```javascript
for (var key in person){
    console.log(key+": "+person[key]);
}
```


### Задание
Нарисовать HTML таблицу из двух колонок, в которой слева будут ключи, а справа - значения:
<table><tr><th>name</th><td>Ivan</td></tr><tr><th>surname</th><td>Ivanovv</td></tr><tr><th>fatherName</th><td>Petrovich</td></tr></table>

## JSON

[**JSON**](http://www.json.org/json-ru.html) (**JavaScript Object Notation**) - синтаксис для хранения древовидных структур данных, который вы видели в примерах выше. Удобен, лаконичен и
нагляден. Строки в формате **JSON** удобно передавать для обмена данными по сети.

- **Сериализацией** назывют преобразование внутренних структур языка программирования в формат, пригодный для хранения; Обычно это строка того или иного формата
- **Десериализацией** называют обратное преобразование. 

```javascript
JSON.stringify(someTree)
JSON.stringify(a)
JSON.parse('{"country": "Ukraine", "city": "Kharkiv"}')
```

JSON более строг, чем схожий синтаксис в JavaScript:
- он требует двойных кавычек вокруг ключей;
- одинарные кавычки использовать нельзя;
- невозможно превратить в JSON-строку объекты с циклическими ссылками;
- поля-методы (функции) не сериализуются
- после последней пары ключ-значение (перед фигурной скобкой) **не** должно быть запятой. В **JS** это допустимо.

## **ES6**

В стандарте языка **ES6** есть дополнительные возможности работы с объктами:

### дублирование ключа-значения и выражение в ключе

```javascript
var age = 25;
var name = 'Vasiliy';
var obj = {
    name, //name: name 
    ["a" + 'ge']: age, //выражение в ключе,
}
```

### rest/spread `...`

```javascript
var obj2 = {...obj, surname: ''} //копируем obj и добавляем еще ключ
var arr2 = [1,2,...[3,4,5]]      //добавление массива в массив
```


## Деструктуризация

**Деструктуризация** позволяет доставать значения полей объектов и массивов по нескольку за одну операцию и избавляет вас от заведения временной переменной для хранения массива или объекта:
```javascript
var [a,b,c] = [1,2,3] //создается три переменных из массива
var {rand1: x, rand2: y, rand3: z} = {rand1: Math.random(), rand2: Math.random(), rand3: Math.random()}
```


## `for .. of`

Работает как `for in` (почти), но перебирает *значения*, а не *ключи*:

```javascript
for (let word of ['foo','bar']){
    console.log(word)
}
```



## Шаблонизация строк `` `

Символ `` ` (*backtick*, обратная кавычка, находится на `Ё`) позволяет вставить выражение в строку без использования конкатенации:

```javascript
alert(`Привет, ${prompt('Имя?')}`)
```