如何在工厂函数中结合闭包、私有变量与Object.assign/Object.create
实现工厂函数闭包私有变量 + 原型方法继承的正确姿势
问题根源
你之前的问题出在:当把方法抽离到projectMethods并通过Object.create继承时,为了让原型方法能访问"私有变量",你可能错误地把闭包里的_title、_tabs挂载到了实例的this上(比如this._title = _title),这直接导致原本的闭包私有变量变成了实例的公开属性。
正确实现方案
核心思路:闭包保存私有变量,公共方法放原型,需要访问私有变量的方法通过闭包绑定到实例
1. 拆分方法:公共方法 + 需访问私有变量的方法
先把不需要访问私有变量的公共方法抽离到单独对象,作为原型继承的基础:
// 公共原型方法(无需访问私有变量) const projectBaseMethods = { logProjectInfo() { console.log('当前项目类型:基础项目'); } };
2. 工厂函数实现:闭包私有变量 + 原型继承 + 闭包方法绑定
在工厂函数内部,用闭包保存私有变量,创建实例时通过Object.create继承公共原型,再用Object.assign把需要访问私有变量的方法添加到实例(这些方法通过闭包直接访问私有变量,无需挂载到this):
function createProject(title) { // 闭包私有变量:外部完全无法直接访问 const _title = title; const _tabs = []; // 创建实例,继承公共原型方法 const projectInstance = Object.create(projectBaseMethods); // 添加需访问私有变量的方法(通过闭包访问,不暴露变量) Object.assign(projectInstance, { getTitle() { return _title; }, addTab(tabName) { _tabs.push(tabName); }, getTabs() { // 返回副本,避免外部修改内部私有数组 return [..._tabs]; }, clearTabs() { _tabs.length = 0; } }); return projectInstance; }
3. 验证效果
const myProject = createProject('我的项目'); console.log(myProject.getTitle()); // 输出:我的项目 myProject.addTab('首页'); console.log(myProject.getTabs()); // 输出:['首页'] // 尝试访问私有变量:undefined,无法直接访问 console.log(myProject._title); // undefined console.log(myProject._tabs); // undefined // 公共原型方法可以正常调用 myProject.logProjectInfo(); // 输出:当前项目类型:基础项目
进阶优化:动态包装原型方法(可选)
如果希望所有方法都在原型上,也可以在工厂函数内部动态创建原型,把公共方法和闭包方法合并:
const projectMethods = { logProjectInfo() { console.log('当前项目类型:基础项目'); } }; function createProject(title) { const _title = title; const _tabs = []; // 动态创建原型:继承公共方法,同时添加闭包方法 const customProto = Object.create(projectMethods); customProto.getTitle = () => _title; customProto.addTab = (tab) => _tabs.push(tab); customProto.getTabs = () => [..._tabs]; return Object.create(customProto); }
注意:这种方式每个实例都会生成一个新的原型对象,性能略低于第一种方案,适合方法数量少的场景。
内容的提问来源于stack exchange,提问作者stuffz
相关产品推荐
相关产品推荐

