
在 javascript 中,对象作为参数传递时始终是“按引用传递”(更准确地说,是按共享引用传递),因此跨模块修改对象属性是可行的;但为保障可维护性与封装性,应避免隐式共享状态,优先通过明确接口通信。
在 javascript 中,对象作为参数传递时始终是“按引用传递”(更准确地说,是按共享引用传递),因此跨模块修改对象属性是可行的;但为保障可维护性与封装性,应避免隐式共享状态,优先通过明确接口通信。
JavaScript 并不存在传统意义上的“传值”或“传引用”二分法,而是采用 “按共享引用传递”(pass-by-sharing):当一个对象被赋值或作为参数传入函数时,实际传递的是该对象在内存中的引用副本。只要不重新赋值变量(即不执行 obj = {...} 或 obj = new SomeClass()),所有持有该引用的地方都能观察到对对象属性的修改——这一机制在模块间完全适用。
例如:
// main.js
import { handleUserEvent } from './handlers.js';
const user = { name: 'Alice', score: 0 };
handleUserEvent(user); // 修改 user.score
console.log(user.score); // 输出 100 —— 修改已生效
// handlers.js
export function handleUserEvent(obj) {
obj.score += 100; // ✅ 直接修改属性,main.js 中可见
// obj = { name: 'Bob' }; // ❌ 重赋值引用,main.js 不受影响
}
然而,技术可行 ≠ 架构推荐。依赖跨模块隐式对象引用会带来显著风险:
-
封装性破坏:
main.js的私有对象被外部模块直接修改,违背模块职责边界; - 调试困难:状态变更点分散,难以追踪谁在何时修改了哪个属性;
-
耦合加剧:
handlers.js与main.js的数据结构强绑定,重构成本高; - 并发/异步隐患:若多个事件处理器并发操作同一对象,可能引发竞态(虽 JS 单线程缓解,但仍影响逻辑清晰度)。
✅ 推荐实践:
- 将模块内状态设为
const声明,禁止重赋值; - 使用不可变更新模式(如
Object.assign({}, original, updates)或结构赋值)生成新对象; - 通过显式 API 通信:导出纯函数(如
updateUser(user, updates))或事件回调(如onUserUpdated(newData)),而非暴露可变对象; - 若需集中管理状态,应使用专用状态容器(如
class Store、Zustand、Pinia 等),而非裸对象跨模块传递。
简言之:JS 对象的引用传递机制本身可靠,但模块设计应以“最小共享”为原则——让数据流动可控、可测、可追溯,而非依赖底层语言特性实现隐式协作。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











