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推荐使用的方法.目前 ...
随机推荐
- 解决:Determining IP Information for eth0...问题
环境:Centos 6.2 VMWare Workstation 7.1.2 故障现象: 在虚拟机中启动Centos,在启动页面中停留在Determining IP Information ...
- 解决Hsqldb指针只能单向移动,不能回滚问题(.first())
Class.forName("org.hsqldb.jdbcDriver").newInstance(); Connection con = java.sql.DriverMana ...
- md5sum 和 sha256sum用于 验证软件完整性
md5sum 和 sha256sum 都用来用来校验软件安装包的完整性,本次我们将讲解如何使用两个命令进行软件安装包的校验: sha 是什么? sha 为 安全散列算法(英语:Secur ...
- 在Ubuntu17.04中遇到无法清空回收站解决方法
在Ubuntu17.04下,遇到清空回收站文件时报错,提示”Failed to delete the item from the trash”,无法清空回收站. 回收站其实就是一个文件夹,存放着被删掉 ...
- Will Georgia Tech's $7K online M.S. in computer science program make the grade?
https://newatlas.com/georgia-tech--graduate-computer-science-degree-mooc/28763/ Georgia Tech to offe ...
- 【C语言】 8421BCD码与二进制的转换
#define BCD2TODEC(bcd) (bcd) = ((bcd) & 0x0f)+ ((bcd)>>4)*10 #define BIN2BCD(bcd) (bcd) = ...
- make报错
笔记本Ubuntu16.04环境下,进入项目的src目录下执行make操作,发现报如下错误 /bin/sh: 1: /usr/bin/libtool: not found makefile:89: r ...
- 实现统计 android手机 CPU使用率
# -*- coding:utf-8 -*- ''' Created on Sep 10, 2018 @author: SaShuangYiBing ''' import subprocess imp ...
- sublime text3 当运行报错error时,取消显示路径path的方法
sublime text3 每当运行报错error时,都会出现一长串的path路径,如何不显示呢? 可以通过注释掉Packages/Default/exec.py的四个特定行来更改. 首先,您需要从P ...
- BZOJ1458:士兵占领(有上下界最小流)
Description 有一个M * N的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵.我们称这些士兵占领了整个棋盘当满足第i行至少放 ...