Node.js 面试题详细答案 - Q8
Q8: exports 和 module.exports 有什么区别?
基本概念
exports
exports 是 module.exports 的引用
- 默认指向同一个对象
- 用于添加属性到模块导出
module.exports
- 模块的真正导出对象
- 可以完全替换导出内容
- 优先级高于
exports
基本区别
使用 exports 添加属性
exports.name = 'MyModule'
exports.version = '1.0.0'
exports.sayHello = function () {
return 'Hello from MyModule'
}
module.exports.name = 'MyModule'
module.exports.version = '1.0.0'
module.exports.sayHello = function () {
return 'Hello from MyModule'
}
使用 module.exports 替换导出
module.exports = {
name: 'MyModule',
version: '1.0.0',
sayHello: function () {
return 'Hello from MyModule'
},
}
详细示例
示例 1:exports 添加属性
exports.name = 'Module1'
exports.getValue = function () {
return 42
}
const module1 = require('./module1')
console.log(module1.name)
console.log(module1.getValue())
示例 2:module.exports 替换导出
module.exports = {
name: 'Module2',
getValue: function () {
return 100
},
}
const module2 = require('./module2')
console.log(module2.name)
console.log(module2.getValue())
示例 3:混合使用的问题
exports.name = 'Module3'
module.exports = {
version: '2.0.0',
}
const module3 = require('./module3')
console.log(module3.name)
console.log(module3.version)
引用关系
初始状态
console.log('exports === module.exports:', exports === module.exports)
console.log('exports:', exports)
console.log('module.exports:', module.exports)
修改后的状态
exports.name = 'Test'
console.log('exports === module.exports:', exports === module.exports)
console.log('exports:', exports)
console.log('module.exports:', module.exports)
module.exports = { version: '1.0.0' }
console.log('exports === module.exports:', exports === module.exports)
console.log('exports:', exports)
console.log('module.exports:', module.exports)
实际应用场景
场景 1:导出多个函数
exports.add = function (a, b) {
return a + b
}
exports.subtract = function (a, b) {
return a - b
}
exports.multiply = function (a, b) {
return a * b
}
const utils = require('./utils')
console.log(utils.add(5, 3))
console.log(utils.subtract(5, 3))
console.log(utils.multiply(5, 3))
场景 2:导出单个函数
module.exports = function (message) {
console.log(`[${new Date().toISOString()}] ${message}`)
}
const logger = require('./logger')
logger('Hello World')
场景 3:导出类
class User {
constructor(name, email) {
this.name = name
this.email = email
}
getName() {
return this.name
}
getEmail() {
return this.email
}
}
module.exports = User
const User = require('./User')
const user = new User('John', 'john@example.com')
console.log(user.getName())
场景 4:导出配置对象
module.exports = {
database: {
host: 'localhost',
port: 5432,
name: 'myapp',
},
server: {
port: 3000,
host: '0.0.0.0',
},
api: {
version: 'v1',
baseUrl: '/api',
},
}
const config = require('./config')
console.log(config.database.host)
console.log(config.server.port)
常见错误
错误 1:直接赋值给 exports
exports = {
name: 'MyModule',
version: '1.0.0',
}
module.exports = {
name: 'MyModule',
version: '1.0.0',
}
错误 2:混合使用导致混乱
exports.name = 'MyModule'
module.exports = { version: '1.0.0' }
exports.description = 'A test module'
module.exports = {
name: 'MyModule',
version: '1.0.0',
description: 'A test module',
}
最佳实践
1. 统一使用 module.exports
module.exports = {
name: 'MyModule',
version: '1.0.0',
methods: {
method1: function () {
return 'method1'
},
method2: function () {
return 'method2'
},
},
}
2. 使用 exports 添加属性
exports.name = 'MyModule'
exports.version = '1.0.0'
exports.method1 = function () {
return 'method1'
}
exports.method2 = function () {
return 'method2'
}
3. 导出函数或类
module.exports = function createUser(name, email) {
return { name, email }
}
module.exports = class User {
constructor(name, email) {
this.name = name
this.email = email
}
}
总结
- exports:
module.exports 的引用,用于添加属性
- module.exports:真正的导出对象,可以完全替换
- 优先级:
module.exports 优先级更高
- 最佳实践:统一使用
module.exports 或 exports,避免混合使用
- 常见错误:直接赋值给
exports 不会生效
- 适用场景:根据导出内容选择合适的导出方式