JavaScript模块模式:如何获取被修改的私有变量并公开访问?
JavaScript模块模式中访问修改后私有变量的问题解析
第一段代码失效的原因
你第一段代码里,模块返回的privateObject是初始空对象的引用,但init函数里是直接给内部的privateObject重新赋值了一个新对象。这时候内部私有变量的引用指向了新内存地址,可外部拿到的还是原来空对象的引用,所以打印结果还是初始的{}。
代码示例:
let Module = (function(){ let privateObject = {}; function init(){ privateObject = {test:true} // 这里是给内部变量换了个新对象 } return { init, privateObject // 返回的是一开始空对象的引用,和内部后来的对象没关系了 } })(); Module.init(); console.log(Module.privateObject); // 输出{}
第二段代码生效的逻辑
第二段代码里,你没有重新赋值整个对象,只是修改了publicObject.privateObject的属性。因为对象是引用类型,外部访问的Module.privateObject和内部操作的是同一个对象,所以修改属性后外部能看到变化。
但要注意:这种写法里的privateObject已经不是严格的私有变量了——外部可以直接修改它的属性(比如Module.privateObject.test = false),如果你的需求是严格保护私有状态,这会是个问题。
代码示例:
let Module = (function(){ function init(){ publicObject.privateObject.test = true; // 只是修改已有对象的属性,引用没换 } let publicObject = { privateObject: {}, init } return publicObject; })(); Module.init(); console.log(Module.privateObject); // 输出{test: true}
更严谨的实现(兼顾私有性和可访问性)
如果既要保持变量的私有性(外部不能直接修改),又能获取修改后的值,推荐用getter方法或者ES6的getter属性:
方式1:手动写getter方法
let Module = (function(){ let privateObject = {}; function init(){ privateObject = {test: true}; // 哪怕重新赋值新对象也没问题 } function getPrivateObject(){ return privateObject; } return { init, getPrivateObject } })(); Module.init(); console.log(Module.getPrivateObject()); // 输出{test: true}
方式2:ES6 getter属性(更像访问普通属性)
let Module = (function(){ let privateObject = {}; function init(){ privateObject = {test: true}; } return { init, get privateObject(){ return privateObject; } } })(); Module.init(); console.log(Module.privateObject); // 输出{test: true}
这两种方式下,外部只能读取私有变量的最新值,无法直接修改内部的私有变量(比如Module.privateObject = {}不会影响内部的privateObject),真正做到了私有状态的保护。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

