В чем разница между module.exports и exports в Node.js?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между module.exports и exports в Node.js
Этот вопрос часто вызывает путаницу у разработчиков. Хотя оба используются для экспорта, между ними есть критическая разница в том, как они работают с ссылками и объектами.
Основная разница
// exports — это ссылка на module.exports
exports === module.exports // true
// Но когда ты переназначаешь exports
exports = { name: 'John' }; // это НЕ меняет module.exports!
Как это работает внутри
Node.js оборачивает каждый модуль в функцию:
(function (exports, require, module, __filename, __dirname) {
// Твой код здесь
// exports и module.exports указывают на один и тот же объект
});
Первоначально:
exports = module.exports = {}; // одна и та же ссылка
Практические примеры
1. Правильный способ — присвоение к module.exports
// math.js
module.exports = {
add: (a, b) => a + b,
subtract: (a, b) => a - b,
};
// main.js
const math = require('./math');
console.log(math.add(5, 3)); // 8
2. Проблема — переназначение exports
// logger.js
exports = {
log: (msg) => console.log(msg),
};
// main.js
const logger = require('./logger');
console.log(logger); // {} — ПУСТО!
// exports переназначена, но module.exports остался пуст
3. Правильное использование exports для добавления методов
// Этот подход работает потому что мы меняем объект, а не ссылку
// user.js
exports.getName = function() {
return 'John';
};
exports.getAge = function() {
return 30;
};
// Эквивалентно
module.exports.getName = function() {
return 'John';
};
module.exports.getAge = function() {
return 30;
};
// main.js
const user = require('./user');
console.log(user.getName()); // 'John'
Важный момент: ссылки vs значения
// РАБОТАЕТ — мы меняем свойства объекта
exports.method = () => console.log('Hello');
// Потому что exports указывает на module.exports
// НЕ РАБОТАЕТ — мы меняем саму ссылку
exports = { method: () => console.log('Hello') };
// Теперь exports указывает на новый объект, а module.exports остался прежним
Сложный пример
// Это НЕ работает
exports = () => console.log('Function');
// require вернет {} потому что module.exports не изменился
// Это РАБОТАЕТ
module.exports = () => console.log('Function');
// require вернет функцию
// Использование
const func = require('./module');
func(); // Function
Применение в современном Node.js
1. Экспорт объекта с методами
// database.js
module.exports = {
connect() {
console.log('Connected');
},
query(sql) {
return [];
},
};
2. Экспорт класса
// User.js
class User {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
module.exports = User;
// main.js
const User = require('./User');
const user = new User('John');
3. Экспорт функции
// utils.js
module.exports = function formatDate(date) {
return date.toLocaleDateString();
};
// main.js
const formatDate = require('./utils');
formatDate(new Date()); // '28.03.2026'
Избежание ошибок
// ❌ ПЛОХО — это не работает
exports = { value: 42 };
// ✅ ХОРОШО
module.exports = { value: 42 };
// ✅ ХОРОШО — добавление свойств
exports.value = 42;
// ✅ ХОРОШО (современный способ)
module.exports.value = 42;
Дебагинг
// Если ты не уверен что экспортируется
console.log('exports:', exports);
console.log('module.exports:', module.exports);
console.log('Одно и тоже?', exports === module.exports);
// После переназначения exports
exports = { test: 123 };
console.log('exports === module.exports:', false);
// Вот почему require не видит твой объект!
Правило большого пальца
Всегда используй module.exports, никогда не переназначай exports:
// ✅ ВСЕГДА ТАК
module.exports = { ... };
module.exports.method = function() { ... };
// ❌ НИКОГДА ТАК
exports = { ... }; // НЕ переназначай!
Почему это было так спроектировано?
Node.js основан на CommonJS, где exports был удобным сокращением для добавления свойств:
// Удобно писать
exports.method = () => {};
// Вместо
module.exports.method = () => {};
Но когда ты хочешь экспортировать что-то целое (объект, класс, функцию), нужно переназначить сам module.exports, а не exports.
Современный Node.js
В наши дни рекомендуется использовать ES6 модули:
// export.js — современный способ
export const add = (a, b) => a + b;
export default { add };
// import.js
import { add } from './export.js';
Но CommonJS все еще используется повсеместно в существующих проектах, поэтому понимание этой разницы критично для работы с Node.js.