# 03. Import

Импорт-выражение позволяет подключить в текущий модуль определения, экспортируемые из другого модуля:

* Импорт выражение должно быть top-level
* Импорты должны быть compile-time resolved
* Нельзя делать условные импорты и т.д.
* Определения, сделанные при помощи импортов, поднимаются как `var`-определения.

## `import`-expression

Импорт выполняется при помощи ключевого слова `import`, после чего идет `import`- выражение (объявления), далее ключевое слово `from` и указывается относительный/абсолютный или URL-путь к модулю.

```javascript
import var from 'module';
```

ES6 provides several styles of importing:

* **Default import**:

```javascript
import localName from "src/my_lib";
```

* **Namespace import**: imports the module as an object (with one property per named export).

```javascript
import * as my_lib from "src/my_lib";
```

* **Named imports**:

```javascript
import { name1, name2 } from "src/my_lib";
```

* You can **rename named imports**:

```javascript
// Renaming: import `name1` as `localName1`
import { name1 as localName1, name2 } from "src/my_lib";
```

* **Empty import**: only loads the module, doesn’t import anything. The first such import in a program executes the body of the module.

```javascript
import "src/my_lib";
```

There are only two ways to combine these styles and the order in which they appear is fixed; the default export always comes first.

* Combining a default import with a namespace import.
* Combining a default import with named imports.

```javascript
// 1.
import theDefault, * as my_lib from "src/my_lib";

// 2.
import theDefault, { name1, name2 } from "src/my_lib";
```

Результатом import-выражения является объявление в текущем пространстве имен определений (bindings) из других модулей. При импорте не выполняется копирование значений из других модулей. Фактически, семантика импорта соответствует определению новой переменной и пере-присваиванию.

Синтаксис named imports похож на деструкцию, но технически ей не является. Нельзя использовать паттерны деструкции в импорте.

## Imports view on exports

Импортированные значения являются read-only представлениями экспортируемых сущностей. Другими словами, любой импорт -- это живое соединение с экспортируемыми элементами.

* Импорты вида `import x from 'foo'` работают аналогично `const`
* Импорты вида `import * as foo from 'foo'` работают аналогично замороженным объектам.
* Можно модифицировать состояние подключенного модуля используя замыкания и другие приемы:

```javascript
//------ lib.js ------
export let counter = 3;
export function incCounter() {
  counter++;
}

//------ main.js ------
import { counter, incCounter } from "./lib";

// The imported value `counter` is live
console.log(counter); // 3
incCounter();
console.log(counter); // 4
```

Если значение внутри модуля поменялось, то его увидят и клиенты этого модуля. Нельзя изменить импортируемое значение, но можно изменить его содержимое, если это объект??

```javascript
//------ lib.js ------
export let obj = {};

//------ main.js ------
import { obj } from "./lib";

obj.prop = 123; // OK
obj = {}; // TypeError
```
