javascript典型bug——错误的闭包
昨天QT给我的一个功能提了一个bug。大概意思就是说,一段在不同位置都会被调用的代码,在A处被调用的时候,似乎会对其他调用的地方产生影响。
我仔细debug了半天,终于找到了原因。简化过的代码如下:
1 function C(name, id){ 2 this.name = name; 3 var privateId = id; 4 if (typeof this.showName != "function") { 5 C.prototype.showName = function(){ 6 console.log(this.name); 7 } 8 C.prototype.showId = function(){ 9 console.log(privateId); 10 } 11 } 12 13 } 14 15 var c1 = new C('name1', 'id1'); 16 var c2 = new C('name2', 'id2'); 17 18 c1.showName(); //name1 19 c1.showId(); //id1 20 c2.showName(); //name2 21 c2.showId(); //id1 !!!!
问题出在最后一行,c2的showId方法打印出了id1。
苦思冥想良久,终于让我想到了问题的原因——c2对象在调用构造函数的时候,不会进入if分支里面!
为什么呢?因为c1在实例化的时候,this.showName = undefined,于是进入if分支,给自己的prototype加上了一个showName方法一个showId方法。
等到c2对象实例化的时候,this.showName已经不再是undefined了,于是不会进入if分支。
这样,c2的showId方法和c1的showId方法是同一个方法,而且这个方法里面打印的privateId变量则都是c1在实例化的时候创建的那个变量,也就是id1。
所以效果就是,本来想把privateId变量申明成一个私有变量,但这样写了之后,它变成了一个static变量了,真是缘木求鱼,南辕北辙啊。
问题原因找到了,那么如何求解呢?
我的思路是,要使用闭包实现私有变量,那么这个闭包的函数就要与需要隐藏的变量绑定起来。而私有变量又是和类的实例绑定的,也就是c1和c2分别有自己的私有变量,所以闭包函数也必须和类的实例一一绑定。于是就改成了这样:
1 function C(name, id){ 2 this.name = name; 3 var privateId = id; 4 if (typeof this.showName != "function") { 5 C.prototype.showName = function(){ 6 console.log(this.name); 7 } 8 9 } 10 11 this.showId = function(){ 12 console.log(privateId); 13 } 14 }
经测试,结果是正确的。
不过我依然在怀疑,我上面说的思路中“闭包的函数就要与需要隐藏的变量绑定起来”这一句,是否是正确的?如果是否,那么还有没有其他的更好的方式实现这个需求呢?
如需转载,请注明转自:http://www.cnblogs.com/silenttiger/p/3443375.html
欢迎关注我的微信公众号:老虎的小窝
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 单线程的Redis速度为什么快?
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库