对象原型方法中私有变量的作用域
这个问题是关于一个对象的行为,该对象的原型链中添加了方法和一些私有变量。 只是出于好奇并想了解这个谜语。
function SomeObject() {
if (this instanceof SomeObject) {
var args = arguments[0],
proto = SomeObject.prototype,
privatevalue = 0,
/** assign first element of args[0]
* (=instance name) to private variable [id],
* to be able to keep track of the instance
*/
id = args[0] ||'no id';
/** public 'set' adds a value to
* the private variable [privatevalue]
*/
this.set =
function(){
privatevalue += arguments[0] || 1;
return privatevalue;
};
/** toString functions as a kind of getter */
this.toString = function(){
return id+' privatevalue: '+privatevalue;
}
/** add two methods to the prototype chain
* this happens only once
*/
if (!proto._initialized_) {
/** SomeObject.prototype.add
* uses 'this.set' to add a value
* to [privatevalue] and returns
* the object value (from tostring)
*/
proto.add =
function(){
this.set(arguments[0]);
return this;
};
/** SomeObject.prototype.add2
* uses 'this.set' to add a value
* to [privatevalue] but returns
* a string using private variables
* [id] and [privatevalue]
*/
proto.add2 =
function(){
this.set(arguments[0]);
return id+' privatevalue: '+privatevalue;
};
proto._initialized_ = true;
}
} else {
return new SomeObject(Array.prototype.slice.call(arguments));
}
}
/** create 2 instances of SomeObject */
var objA = SomeObject('objA'),
objB = SomeObject('objB');
/** show the values and use the prototype [add] method
* to change [privatevalue]
*/
alert ([objA, objB].join(' | '));
//=> objA privatevalue: 0 | objB privatevalue: 0
alert ([objA.add(4), objB.add(2)].join(' | '));
//=> objA privatevalue: 4 | objB privatevalue: 2
/** use prototype method 'add2' to change and view the
* private variables [id] and [privatevalue] for objA
*/
alert (objA.add2());
//=> objB privatevalue: 2!
现在的问题是:为什么 ojbA 的原型方法 add2 (因此:objA.add2())返回 objB 的私有变量的值? 我想说 objA 不应该访问这些私有的。 换句话说:这里发生了什么样的范围界定? 还是陌生人。 如果这样做:
alert (objA.add2());
alert (objB.add2());
您将得到 for objA.add2(): objA privatevalue: 5
和 for objB.add(): objA privatevalue: 5
This question is about the behavior of an object with methods added to its prototype chain and a few private variables. Just out of curiosity and to get my head around this riddle.
function SomeObject() {
if (this instanceof SomeObject) {
var args = arguments[0],
proto = SomeObject.prototype,
privatevalue = 0,
/** assign first element of args[0]
* (=instance name) to private variable [id],
* to be able to keep track of the instance
*/
id = args[0] ||'no id';
/** public 'set' adds a value to
* the private variable [privatevalue]
*/
this.set =
function(){
privatevalue += arguments[0] || 1;
return privatevalue;
};
/** toString functions as a kind of getter */
this.toString = function(){
return id+' privatevalue: '+privatevalue;
}
/** add two methods to the prototype chain
* this happens only once
*/
if (!proto._initialized_) {
/** SomeObject.prototype.add
* uses 'this.set' to add a value
* to [privatevalue] and returns
* the object value (from tostring)
*/
proto.add =
function(){
this.set(arguments[0]);
return this;
};
/** SomeObject.prototype.add2
* uses 'this.set' to add a value
* to [privatevalue] but returns
* a string using private variables
* [id] and [privatevalue]
*/
proto.add2 =
function(){
this.set(arguments[0]);
return id+' privatevalue: '+privatevalue;
};
proto._initialized_ = true;
}
} else {
return new SomeObject(Array.prototype.slice.call(arguments));
}
}
/** create 2 instances of SomeObject */
var objA = SomeObject('objA'),
objB = SomeObject('objB');
/** show the values and use the prototype [add] method
* to change [privatevalue]
*/
alert ([objA, objB].join(' | '));
//=> objA privatevalue: 0 | objB privatevalue: 0
alert ([objA.add(4), objB.add(2)].join(' | '));
//=> objA privatevalue: 4 | objB privatevalue: 2
/** use prototype method 'add2' to change and view the
* private variables [id] and [privatevalue] for objA
*/
alert (objA.add2());
//=> objB privatevalue: 2!
Now the question is: why does the prototype method add2 from ojbA (thus: objA.add2()) return the values of the private variables from objB? I would say these privates shouldn't be accessible for objA. In other words: what kind of scoping is going on here?
Stranger still. If you do this:
alert (objA.add2());
alert (objB.add2());
you get for objA.add2(): objA privatevalue: 5
and for objB.add(): objA privatevalue: 5
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题在于您创建添加函数的范围。
当您实例化“objA”时,它们是在 SomeObject 执行范围内创建的。
因此,无论您是再次调用“objA”还是“objB”,Add2 访问的 id 和 privatevalue 变量都属于“objA”。
从根本上讲,基于原型的方法无法访问类的私有成员。 为了访问私有成员,需要在这些成员的相同作用域(或子作用域)中创建一个函数。 这就是 set 起作用的原因,因为它是在 SomeObject 的每个实例上创建的。
The problem is the scope in which you create the add functions.
They are created in the scope of SomeObject execution when you instantiate 'objA'.
Hence id and privatevalue variables accessed by Add2 are the ones belonging to 'objA' regardless of whether you call .Add2 agains 'objA' or 'objB'.
Fundementally prototype based methods cannot to access private members of a class. In order to access private members a function needs to be created in the same scope (or a child scope) of those members. This is why set works because its created on each instantiaion of SomeObject.