Export: примеры (JAVASCRIPT)
export(declaration (any)): -Основы экспорта в JavaScript
Ключевое слово export используется в JavaScript для экспорта функций, объектов, примитивных значений или классов из модуля, чтобы они стали доступными для других модулей с помощью оператора import. Экспорт применяется только в модулях (файлах с типом module).
Использование: Экспорт необходим для создания модульной архитектуры в приложениях, позволяя разбивать код на переиспользуемые и изолированные части.
Варианты синтаксиса:
- Именованный экспорт (Named Export): Позволяет экспортировать несколько значений из модуля, указывая их имена. Может использоваться как при объявлении, так и после него.
- Экспорт по умолчанию (Default Export): Позволяет экспортировать одно главное значение из модуля (функцию, класс или объект).
- Реэкспорт (Re-export): Позволяет агрегировать и экспортировать значения из других модулей.
У оператора export нет аргументов или возвращаемых значений в традиционном понимании функции. Это декларация, которая определяет, какие части модуля становятся публичными.
Базовые примеры использования
Именованный экспорт при объявлении
Экспорт константы и функции непосредственно в момент их создания.
// module.js
export const apiKey = '123abc';
export function sum(a, b) {
return a + b;
}
export class Calculator {
multiply(x, y) { return x * y; }
}// При импорте в другом файле:
// import { apiKey, sum, Calculator } from './module.js';Именованный экспорт списком
Экспорт нескольких значений, объявленных ранее.
// module.js
const greeting = 'Hello';
const dbUrl = 'localhost:5432';
function log(message) { console.log(message); }
export { greeting, dbUrl, log };Экспорт по умолчанию
Экспорт одного основного значения из модуля.
// userService.js
export default class UserService {
getUser(id) { return { id, name: 'John' }; }
}
// или для функции
export default function(config) {
console.log(config);
}// При импорте: // import UserService from './userService.js'; // Имя может быть любым
Комбинированный экспорт
Использование именованного экспорта и экспорта по умолчанию вместе.
// utils.js
export const version = '1.0';
export function helper() {}
const mainUtil = () => {};
export default mainUtil;// Импорт:
// import mainUtil, { version, helper } from './utils.js';Альтернативные системы модулей в JavaScript
CommonJS (используется в Node.js)
Использует module.exports и require(). Это синхронная система, исторически применяемая в серверной среде Node.js.
// Экспорт
module.exports = { key: 'value' };
// или
exports.item = function() {};
// Импорт
const lib = require('./lib');Когда использовать: В проектах Node.js, не перешедших на нативные ES-модули, или в инструментах сборки, таких как Webpack или Browserify, которые могут транспилировать код.
AMD (Asynchronous Module Definition)
Использует функцию define. Создана для асинхронной загрузки модулей в браузере. Наиболее известная реализация — RequireJS.
define(['dependency1', 'dependency2'], function(dep1, dep2) {
return {
myExport: function() {}
};
});Когда использовать: В устаревших браузерных проектах, где важна асинхронная загрузка без сборщиков.
Предпочтения: Для современных веб-приложений и библиотек стандартом являются ES-модули (export/import) из-за их нативной поддержки в браузерах и Node.js, статической анализируемости и асинхронной природы.
Экспорт в других языках программирования
Python (import/from)
В Python каждый файл .py является модулем. Экспорт всего содержимого модуля управляется соглашениями и списком __all__.
# mymodule.py
def public_func():
return "Hello"
def _private_func():
return "Secret"
__all__ = ['public_func'] # Определяет, что импортируется при from module import *# Импорт в другом файле from mymodule import public_func print(public_func()) # Hello # _private_func не будет доступна при импорте через *
PHP (namespace/use)
PHP использует пространства имен (namespaces) и ключевые слова use для импорта. Экспорт как таковой отсутствует — доступно все, что объявлено в файле.
// File: MyApp/Utils.php
<?php
namespace MyApp;
class Utils {
public static function filter($data) { return $data; }
}
function helper() {}
// Импорт в другом файле <?php use MyApp\Utils; use function MyApp\helper; Utils::filter([]); helper();
C/C++ (header files)
В C/C++ используется механизм заголовочных файлов (.h), которые содержат объявления функций и переменных. Определения находятся в файлах реализации (.c/.cpp).
// mylib.h - заголовочный файл ("экспорт")
#ifndef MYLIB_H
#define MYLIB_H
extern int global_var; // Объявление глобальной переменной
int add(int a, int b); // Объявление функции
#endif
// mylib.c - файл реализации
#include "mylib.h"
int global_var = 10;
int add(int a, int b) { return a + b; }Ключевое отличие: В отличие от JavaScript, где export является частью языка и контролирует видимость на уровне модуля, в C/C++ видимость регулируется линковщиком, а в PHP и Python — в основном соглашениями и пространствами имен.
Распространенные ошибки
Использование export вне модуля
Ключевое слово export работает только внутри файлов-модулей.
<script>
export let x = 1; // ОШИБКА!
</script>
<script type="module">
export let x = 1; // Корректно
</script>SyntaxError: Unexpected token 'export'
Попытка экспорта необъявленной переменной
// module.js
export { someVariable }; // ОШИБКА: someVariable не объявлена вышеSyntaxError: The requested module does not provide an export named 'someVariable'
Несколько экспортов по умолчанию в одном модуле
В одном модуле может быть только один export default.
// module.js
export default function() {};
export default class {}; // ОШИБКА: Повторный экспорт по умолчаниюSyntaxError: Duplicate export of 'default'
Ошибки при реэкспорте
Попытка реэкспорта несуществующего именованного экспорта.
// aggregator.js
export { nonExistent } from './someModule.js'; // ОШИБКАSyntaxError: The requested module does not provide an export named 'nonExistent'
Изменения и современное состояние
Синтаксис export был стандартизирован в спецификации ECMAScript 2015 (ES6). С тех пор его ядро остаётся стабильным.
Динамический импорт (ES2020)
Хотя напрямую не меняет export, появление выражения import() для динамической загрузки модулей расширило экосистему. Модули с export могут теперь загружаться условно.
if (userNeedsFeature) {
import('./advancedModule.js')
.then(module => {
module.advancedFunction();
});
}Поддержка в Node.js
Ранние версии Node.js поддерживали только CommonJS. Нативная поддержка ES-модулей (с export/import) стабильно доступна с Node.js версии 14.x и выше. Для использования необходимо указать "type": "module" в package.json или использовать расширение файла .mjs.
Экспорт полей пространства имен (Export Namespace)
Синтаксис export * as namespace from 'module' был добавлен и теперь широко поддерживается, позволяя реэкспортировать все именованные экспорты как один объект.
Расширенные и специализированные примеры
Реэкспорт с переименованием и агрегация
Создание единой точки входа для библиотеки, состоящей из нескольких модулей.
// lib/index.js (основной файл библиотеки)
export { default as AuthService } from './auth.js';
export { getUser, setUser } from './user.js';
export * as constants from './constants.js'; // Экспорт всех как объект
export { fetchApi as fetch } from './network.js'; // Реэкспорт с переименованием// Использование в приложении
import { AuthService, fetch, constants } from './lib/index.js';
console.log(constants.API_URL);Экспорт изменяемых привязок (live bindings)
Именованный экспорт создаёт "живую привязку" к переменной, а не копию значения.
// counterModule.js
export let counter = 0;
export function increment() {
counter++;
}
// main.js
import { counter, increment } from './counterModule.js';
console.log(counter); // 0
increment();
console.log(counter); // 1 (значение изменилось!)0 1
Экспорт с условиями (паттерн)
Динамическое определение того, что экспортировать, невозможно, но можно использовать паттерн агрегации.
// featureDetect.js
import { FeatureA } from './features/FeatureA.js';
import { FeatureB } from './features/FeatureB.js';
const enabledFeatures = [];
if (supportsFeatureA) enabledFeatures.push(FeatureA);
if (supportsFeatureB) enabledFeatures.push(FeatureB);
// Экспортируем только то, что доступно
export { FeatureA, FeatureB }; // Экспорт всегда статичен
// Динамический экспорт невозможен, но можно экспортировать объект:
export const features = { FeatureA, FeatureB };Кольцевые зависимости (Circular Dependencies)
Экспорт позволяет создавать кольцевые зависимости, но их следует избегать. Модули загружаются корректно благодаря "живым привязкам".
// moduleA.js
import { funcB } from './moduleB.js';
export function funcA() {
console.log('A');
funcB();
}
// moduleB.js
import { funcA } from './moduleA.js';
export function funcB() {
console.log('B');
// funcA(); // Вызовет потенциальную бесконечную рекурсию
}Экспорт встроенных объектов (polyfills)
Экспорт для расширения или модификации встроенных объектов в рамках модуля.
// arrayUtils.js
if (!Array.prototype.customFlat) {
Array.prototype.customFlat = function() { /* реализация */ };
}
// Экспортируем сам патч как функцию по умолчанию
export default function patchArray() {
// код патча выше
}
// Также можно экспортировать утилиты, не загрязняя глобальную область видимости
export function flattenArray(arr) { /* чистая функция */ }