javascript - js 构造函数私有变量的问题
PHP中文网
PHP中文网 2017-04-11 12:58:20
[JavaScript讨论组]

示例代码如下:

function foo () {
  var bar = 0;
  this.set_one = function (x) { 
    bar = x; 
  }
  this.get_one = function () { 
    return bar; 
  }
  foo.prototype.set_all = function (x) { 
    bar = x; 
  }
  foo.prototype.get_all = function () { 
    return bar; 
  }
}

var a = new foo()
var b = new foo()
var c = new foo()

// 以下代码每次打开一条,测试返回结果
// a.set_one(1)  - 返回 1 0 0 0 0 0
// a.set_all(1)  - 返回 0 1 0 1 1 1
// b.set_one(1)  - 返回 0 0 1 0 0 0
// b.set_all(1)  - 返回 0 1 0 1 1 1
// c.set_one(1)  - 返回 0 1 0 1 1 1
// c.set_all(1)  - 返回 0 1 0 1 1 1

console.log(a.get_one(), a.get_all(), b.get_one(), b.get_all(), c.get_one(), c.get_all())

问题:解释这种结果出现的原因。
我对这个问题比较不解,主要困惑在于这个私有变量bar,如果说在这里这个bar在foo的实例和prototype上都创建了一个,并且互不相干,可以解释a和b的结果,但是这个实例c里的bar和foo的prototype是完全同步的,感觉又像是同一个变量。
我测试了下,如果把c去掉,那么b的表现就和被去掉之前的c一样了,也就是说,最后一个创建的实例就会和前面所有的实例表现相背。
希望各位高手能给解释下其中的原理。

感谢回答的同学,我试着用自己对该回答的理解解释一下这个问题:
当创建第一个对象a时,设a的bar存储于地址1,a.get/set_one和a.get/set_all都是访问地址1的bar.
当再创建一个对象b时,设b的bar存储于地址2,那么b.get/set_one和b.get/set_all是访问地址2的bar,但由于get/set_all是原型方法,所以a.get/set_all也变成了访问地址2的bar
依次类推,当创建对象c时,c.get/set_one是访问地址3的bar,而所有对象的get/set_all也都变成了访问地址3的bar。
用一个表来表示,就是:

操作 a.get_one() a.get_all() b.get_one() b.get_all() c.get_one() c.get_all()
bar内存地址 1 3 2 3 3 3
a.set_one(修改地址1) 1 0 0 0 0 0
a.set_all(修改地址3) 0 1 0 1 1 1
b.set_one(修改地址2) 0 0 1 0 0 0
b.set_all(修改地址3) 0 1 0 1 1 1
c.set_one(修改地址3) 0 1 0 1 1 1
c.set_all(修改地址3) 0 1 0 1 1 1

ps: sf你这个markdown有问题啊,为什么居中对表头无效啊。。

PHP中文网
PHP中文网

认证高级PHP讲师

全部回复(1)
PHP中文网

当你只new一个实例的时候,显而易见,foo.prototype函数中引用的bar和实例中函数引用的bar是同一个。当你继续new一个函数的时候,实例中的属性会重新开一个新的内存地址,但是prototype中的不会,都是指向同一个对象,但是新new出来对象后,foo.prototype函数引用的bar其实是你最后一个bar。所以你调用前面的set_all其实都是修改最后一个实例中的bar。反之你修改最后的bar也会影响前面对象的get_all

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号