javascript典型bug——错误的闭包
昨天QT给我的一个功能提了一个bug。大概意思就是说,一段在不同位置都会被调用的代码,在A处被调用的时候,似乎会对其他调用的地方产生影响。
我仔细debug了半天,终于找到了原因。简化过的代码如下:
function C(name, id){
this.name = name;
var privateId = id;
if (typeof this.showName != "function") {
C.prototype.showName = function(){
console.log(this.name);
}
C.prototype.showId = function(){
console.log(privateId);
}
}
}
var c1 = new C('name1', 'id1');
var c2 = new C('name2', 'id2');
c1.showName(); //name1
c1.showId(); //id1
c2.showName(); //name2
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分别有自己的私有变量,所以闭包函数也必须和类的实例一一绑定。于是就改成了这样:
function C(name, id){
this.name = name;
var privateId = id;
if (typeof this.showName != "function") {
C.prototype.showName = function(){
console.log(this.name);
}
}
this.showId = function(){
console.log(privateId);
}
}
经测试,结果是正确的。
不过我依然在怀疑,我上面说的思路中“闭包的函数就要与需要隐藏的变量绑定起来”这一句,是否是正确的?如果是否,那么还有没有其他的更好的方式实现这个需求呢?
如需转载,请注明转自:http://www.cnblogs.com/silenttiger/p/3443375.html
欢迎关注我的微信公众号:老虎的小窝
javascript典型bug——错误的闭包的更多相关文章
- javascript中的错误处理机制
× 目录 [1]对象 [2]类型 [3]事件[4]throw[5]try[6]常见错误 前面的话 错误处理对于web应用程序开发至关重要,不能提前预测到可能发生的错误,不能提前采取恢复策略,可能导致较 ...
- 【转】《深入理解计算机系统》C程序中常见的内存操作有关的典型编程错误
原文地址:http://blog.csdn.net/slvher/article/details/9150597 对C/C++程序员来说,内存管理是个不小的挑战,绝对值得慎之又慎,否则让由上万行代码构 ...
- 错误内存【读书笔记】C程序中常见的内存操作有关的典型编程错误
题记:写这篇博客要主是加深自己对错误内存的认识和总结实现算法时的一些验经和训教,如果有错误请指出,万分感谢. 对C/C++程序员来讲,内存管理是个不小的挑战,绝对值得慎之又慎,否则让由上万行代码构成的 ...
- 《深入理解计算机系统》C程序中常见的内存操作有关的典型编程错误
对C/C++程序员来说,内存管理是个不小的挑战,绝对值得慎之又慎,否则让由上万行代码构成的模块跑起来后才出现内存崩溃,是很让人痛苦的.因为崩溃的位置在时间和空间上,通常是在距真正的错误源一段距离之后才 ...
- javascript 函数和作用域(闭包、作用域)(七)
一.闭包 JavaScript中允许嵌套函数,允许函数用作数据(可以把函数赋值给变量,存储在对象属性中,存储在数组元素中),并且使用词法作用域,这些因素相互交互,创造了惊人的,强大的闭包效果.[upd ...
- Error: Bootstrap's JavaScript requires jQuery错误
引入bootstrap时会出现的问题:boostrap下拉菜单无效,浏览器报Uncaught Error: Bootstrap's JavaScript requires jQuery错误, 解决办法 ...
- 前端学习 第六弹: javascript中的函数与闭包
前端学习 第六弹: javascript中的函数与闭包 当function里嵌套function时,内部的function可以访问外部function里的变量 function foo(x) { ...
- Javascript 内核Bug
Javascript 内核Bug: js 执行(9.9+19.8)加法运算 等于 29.700000000000003) <html> <head> <title> ...
- javascript(面向对象,作用域,闭包,设计模式等)
javascript(面向对象,作用域,闭包,设计模式等) 1. 常用js类定义的方法有哪些? 参考答案:主要有构造函数原型和对象创建两种方法.原型法是通用老方法,对象创建是ES5推荐使用的方法.目前 ...
随机推荐
- 使用 Azure PowerShell 模块创建和管理 Windows VM
Azure 虚拟机提供完全可配置的灵活计算环境. 本教程介绍 Azure 虚拟机的基本部署项目,例如选择 VM 大小.选择 VM 映像和部署 VM. 你将学习如何执行以下操作: 创建并连接到 VM 选 ...
- SqlServer PIVOT函数快速实现行转列,UNPIVOT实现列转行
我们在写Sql语句的时候没经常会遇到将查询结果行转列,列转行的需求,拼接sql字符串,然后使用sp_executesql执行sql字符串是比较常规的一种做法.但是这样做实现起来非常复杂,而在SqlSe ...
- Go 在 TiDB 的实践
https://blog.csdn.net/RA681t58CJxsgCkJ31/article/details/79215751 更多TiDB链接: https://my.oschina.net/z ...
- Tidb缩减tikv机器
生产环境下,如何缩减机器? 1.首先是检查出来那个tikv节点需要缩减 " -d store { ", "stores": [ { "store&qu ...
- 打开word文档时提示“Microsoft Office Word已停止工作”
我的电脑(Win10)有Office 2003和2013两个版本,可能由于之前超长待机等原因导致word 2003的文件(.doc)不能正常打开,没次都会提示“Microsoft Office Wor ...
- JQuery 为radio赋值问题
今天用jquery 为radio赋值,从百度查了一下方法: $("input[name='radioName'][value=2]").attr("checked&quo ...
- 网络编程_UDP协议_聊天程序
发送端:(将数据源改为键盘录入) import java.io.BufferedReader; import java.io.IOException; import java.io.InputStre ...
- 【转】使用程序修改系统(IE)代理设置
文章都是发布在github再转到这边的,这边格式可能会乱掉.博客地址:benqy.com 这是本人在做的一个前端开发调试工具(HttpMock),功能是web服务器+http日记+http代理(类似f ...
- JS实现拖动div层移动
JS实现拖动div层移动 在谈到拖动div层之前,我们有必要来了解下 下面JS几个属性的区别---- pageX,pageY,layerX,layerY,clientX,clientY,screen ...
- JAVA框架Struts2(二)
一:Struts2执行流程: 1)编写页面,点击超链接,请求提交到服务器端. 2)请求先经过Struts2核心过滤器(StrutsprepareAndexectuterfilter). 3)过滤器的功 ...