---
title: "Пространство имён: область видимости или адрес?"
description: "Сравнение пространства имён в Java, PHP и JavaScript: почему оно одновременно задаёт контекст и помогает находить код."
date: 2022-11-03
---

Сравним понятие `namespace` в Java, PHP и JavaScript. В общем смысле
пространство имён — набор знаков для идентификации объектов; оно делает
имена уникальными и позволяет на них ссылаться. Оно также задаёт
контекст, поэтому слова «пространство имён» и «область видимости» часто
употребляют рядом.

## Java

В Java пространство имён называется `package`:

``` java
package java.awt.event;
```

Каждый класс обычно расположен в отдельном файле, а пакеты образуют
иерархию. Поэтому исходник `java.applet.AppletContext` ожидаемо
находится по адресу `./java/applet/AppletContext.java`, а
`java.awt.event.ActionListener` — в
`./java/awt/event/ActionListener.java`. Файловая система обеспечивает
уникальность идентификаторов, а пакет создаёт контекст: классы без
явного модификатора доступа доступны друг другу внутри пакета.

Для глобальной уникальности Java заимствует DNS: владельцу `company.com`
предлагается использовать пакет `com.company`. Поэтому в Java
пространство имён прежде всего адресует код и уже затем ограничивает
область видимости.

## PHP

В PHP пространства имён появились с версии 5.3 и ещё ближе к файловой
системе:

``` php
namespace Zend;
```

Технически в одном файле допустимо несколько пространств имён, но это не
рекомендуемая практика. Они вкладываются друг в друга и могут
адресоваться абсолютно или относительно — подобно пути в файловой
системе, где alias напоминает символьную ссылку.

``` php
namespace Project;
use Project\ModuleA as ModA;
$modA = new ModuleA();
$modA2 = new ModA();
```

PHP даёт более гибкую адресацию, чем Java, но в обоих языках разработчик
и IDE находят исходник по полному имени (FQN). И, как у Java-пакета,
пространство имён создаёт свой контекст.

## JavaScript

В самом JavaScript нет конструкций `namespace` или `package`.
Классический ответ на вопрос «как объявить namespace?» — создать
именованную область видимости:

``` js
const MyNamespace = (function () { /* ... */ })();
```

Такой «namespace» в JS прежде всего про изоляцию, а не про адрес.
Вложенные области могут содержать одинаково названную функцию:

``` js
const MyNamespace = (() => {
  function myFunc() { console.log('Main space.'); }
  return { fn: myFunc };
})();
((mainSpace) => {
  function myFunc() { console.log('Nested space.'); }
  mainSpace.subSpace = { fn: myFunc };
})(MyNamespace);
```

Во время выполнения они изолированы, но для человека и IDE трудно
получить уникальный адрес каждой `myFunc`. «Copy Reference» часто даёт
только имя функции, а «Find Usage» становится малополезным в очень
большом проекте. Отчасти это объясняет появление TypeScript.

Современный JavaScript с ES-модулями и npm намного ближе к потребностям
больших проектов, но единое, общепринятое правило глобальной адресации
элементов кода всё ещё нужно проекту задавать дисциплиной и
инструментами.

## Вывод

Пространство имён — и адрес, и область видимости, как обычный почтовый
адрес и реальное место. Каждый адрес указывает на место, но не у каждого
места есть собственный адрес. Главное назначение namespace — помочь
разработчику адресовать исходный код, а не компьютеру обратиться к
объекту во время выполнения.

<zoom-img src="/medium/img/9037fada36f2/image-01.jpg" alt="Адрес и место как метафора пространства имён" width="100%"></zoom-img>
