ES6语法下揭示模块模式探究:默认值与私有变量访问疑问
解答你的揭示模块模式(RM)相关疑问
1. 揭示模块模式必须是IIFE吗?
没错,这是该模式的核心要求。揭示模块模式的本质就是靠立即执行函数表达式(IIFE)创建私有作用域,通过闭包把私有变量/方法牢牢封装在函数内部,只向外暴露你指定的接口。如果不加末尾的(),变量_就只是个普通函数,而非执行后返回的对象——这就是你一开始遇到“状态依赖是否加调用”问题的根源:只有执行函数,才会生成私有作用域、初始化变量,并返回暴露的对象。
2. 为什么_._x可以被赋值?这合理吗?
这其实是你代码里的一个小误区,不是私有变量被修改了,而是你给返回的对象新增了一个公共属性:
- 函数内部的
_x是真正的私有变量,只存在于IIFE的作用域里,外部根本无法直接访问(除非你主动暴露它)。 - 你返回的对象里原本没有
_x属性,当你执行_._x = 'fish-ly'时,JS会自动给这个对象添加一个名为_x的公共属性——这个属性和闭包里的私有_x完全是两回事。 - 你的
get x()里写的是return this._x,这里的this指向返回的对象,所以它拿的是对象上的公共_x属性,而非私有变量。如果你想让get x()返回私有变量,应该直接写return _x(去掉this.),这样才能利用闭包访问到函数内部的私有变量。
这种行为是JS的正常特性,但确实违背了揭示模块模式的封装初衷——毕竟直接操作对象的未暴露属性,相当于破坏了私有性,所以才说“strongly discouraged”。
3. 揭示模块模式里可以用ES6默认值吗?
当然可以!你代码里的函数参数默认值_x = 'fish', _y = 'chicken', _z = 'beef'完全合法,只要函数被执行(也就是IIFE的()),这些默认值就会被用来初始化私有变量,完全适配ES6语法规范。
4. 关于_.x[_._x]的报错原理
先拆解你的代码逻辑:
- 你先给
_._x赋值了'fish-ly',此时返回的对象_多了一个公共属性_x: 'fish-ly'。 - 你的
get x()返回this._x,理论上应该拿到'fish-ly',但你测试里console.log(_.x)显示undefined,大概率是代码执行顺序问题(比如赋值操作没生效),或者之前的逻辑导致this._x未被正确赋值。 - 当你执行
_.x[_._x]时,如果_.x是undefined,就相当于尝试执行undefined['fish-ly'],自然会抛出Cannot read property 'fishly' of undefined的错误。 - 退一步说,哪怕
_.x是字符串'fish-ly','fish-ly']['fish-ly']也只会返回undefined(因为字符串的索引只能是数字,访问非数字键会返回undefined),但不会报错——所以核心问题还是_.x此时为undefined。
内容的提问来源于stack exchange,提问作者Tim Pozza
相关产品推荐
相关产品推荐

