![](/img/trans.png)
[英]Javascript: Event inside a function object created with the new keyword
[英]JavaScript new object inside function
我在JavaScript中的OOP有一个问题。 在下面的例子中,当newObj.position.x
增加, newObj.x
没有增加,尽管我写的事实this.x = this.position.x
。 你能告诉我为什么会这样吗?
ClassOne = function( x, y ) { this.x = x; this.y = y; }; ClassTwo = function( x, y, w, h ) { this.x = x; this.y = y; this.w = w; this.h = h; this.position = new ClassOne( this.x, this.y ); this.x = this.position.x; this.y = this.position.y; } var newObj = new ClassTwo( 10, 20, 30, 40 ); for ( var i = 0; i < 15; i++ ) { newObj.position.x++; console.log( newObj.x ); }
console.log的结果是10、10、10、10、10 ...
当您使用new
创建Object
,它将在heap
分配单独的内存。 因此,语句this.position = new ClassOne( this.x, this.y );
为this.position
分配新的内存,现在this.position.x
和this.x
都属于单独的内存。 因此,当您更改newObj.position.x
的实例属性时,这不会反映到newObj.x
如果要使两个属性始终相等,则可以使用getter和setter(并且我将使用类语法,因为我喜欢它):
class Position {
constructor(x,y){
this.x = x;
this.y = y;
}
toString(){
return this.x+":"+this.y;
}
}
class Instance {
constructor(x,y,w,h){
this.w = w;
this.h = h;
this.position = new Position(x,y);
}
get x(){
return this.position.x;
}
set x(x){
this.position.x = x;
}
get y(){
return this.position.y;
}
set y(y){
this.position.y = y;
}
}
所以可以做到:
var player = new Instance(0,0,0,0);
player.x++;
player.position;//0:1
尝试将class
与getter和setter成员方法一起使用,以便它在内部引用position
的值:
class One { constructor (x, y) { this.x = x this.y = y } } class Two { constructor (x, y, w, h) { this.w = w this.h = h this.position = new One(x, y) } get x () { return this.position.x } set x (v) { return this.position.x = v } get y () { return this.position.y } set y (v) { return this.position.y = v } } let newObj = new Two(10, 20, 30, 40) for (let i = 0; i < 15; i++) { newObj.position.x++ console.log(newObj.x) }
newObj.position.x
和newObj.x
是2个不同的值。
通过做
newObj.position.x++
您正在增加newObj
的position
字段的x
字段。 因此, newObj
本身的x
字段不会更改,因为2个字段未链接。
链接它们的一种方法是添加访问器。
使用function objects
,您可以创建如下function objects
:
ClassOne = function (x, y) {
this.x = x;
this.y = y;
};
ClassTwo = function (x, y, w, h) {
this.w = w;
this.h = h;
this.position = new ClassOne(x, y);
Object.defineProperty(this, 'x', {
get: function () { return this.position.x; },
set: function (newValue) { this.position.x = newValue; },
enumerable: true,
configurable: true
});
Object.defineProperty(this, 'y', {
get: function () { return this.position.y; },
set: function (newValue) { this.position.y = newValue; },
enumerable: true,
configurable: true
});
}
var newObj = new ClassTwo(10, 20, 30, 40);
for (var i = 0; i < 15; i++) {
newObj.position.x++;
console.log(newObj.x);
}
编辑:看到其他答案后,我想说的是,我知道使用es6类更好(至少出于可读性考虑),但我想保留OP的功能。
@ArunRedhu的答案完全错了。 这与newObj
和newObj.position
是独立的对象无关,而与x
和y
是原始值这一事实无关。
如果您将问题中提供的代码保留为完全相同的内容,只是用非原始值(例如数组)替换传递给ClassTwo
构造函数的x
和y
值,则属性将按预期反映,如该答案的底部所示。 。 这证明了原因与堆内存中单独对象的实例化无关,而仅仅是由于所使用参数类型的结果。
基元和非基元之间的区别在于,基元是按值传递的,而非基元是按引用传递的。 因此,将原语分配给另一个变量或属性将导致该值被复制而不是被引用。
ClassOne = function( x, y ) { this.x = x; this.y = y; }; ClassTwo = function( x, y, w, h ) { this.x = x; this.y = y; this.w = w; this.h = h; this.position = new ClassOne( this.x, this.y ); this.x = this.position.x; this.y = this.position.y; } var newObj = new ClassTwo( [10], [20], 30, 40 ); for ( var i = 0; i < 15; i++ ) { newObj.position.x[0]++; console.log( newObj.x[0] ); }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.