javascript - js 构造函数私有变量的问题

查看:101
本文介绍了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆