javascript - js 构造函数私有变量的问题
问题描述
示例代码如下:
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有问题啊,为什么居中对表头无效啊。。
当你只new一个实例的时候,显而易见,foo.prototype函数中引用的bar和实例中函数引用的bar是同一个。当你继续new一个函数的时候,实例中的属性会重新开一个新的内存地址,但是prototype中的不会,都是指向同一个对象,但是新new出来对象后,foo.prototype函数引用的bar其实是你最后一个bar。所以你调用前面的set_all其实都是修改最后一个实例中的bar。反之你修改最后的bar也会影响前面对象的get_all
这篇关于javascript - js 构造函数私有变量的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!