我在JavaScript中有一个OOP问题。在下面的示例中,当Array(loop(0)(1.plus).take(4))
增加时,newObj.position.x
不会增加,尽管我写了newObj.x
。你能告诉我为什么会这样吗?
this.x = this.position.x
console.log的结果是10,10,10,10,10 ......
答案 0 :(得分:2)
当您使用Object
创建new
时,它会在heap
中分配单独的内存。因此,语句this.position = new ClassOne( this.x, this.y );
为this.position
分配新内存,现在this.position.x
和this.x
都属于单独的内存。因此,当您更改newObj.position.x
的实例属性时,这不会反映到newObj.x
答案 1 :(得分:2)
如果你想让两个属性始终相等,你可以使用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
答案 2 :(得分:2)
尝试将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)
}
答案 3 :(得分:2)
newObj.position.x
和newObj.x
是两个不同的值。
做
newObj.position.x++
您正在增加x
position
字段的newObj
字段。因此,x
本身的newObj
字段不会更改,因为2个字段未链接。
链接它们的一种方法是添加访问者。
使用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的功能。
答案 4 :(得分:1)
@ArunRedhu's answer完全忽略了这一点。这与newObj
和newObj.position
是独立的对象无关,而与x
和y
是原始值的事实有关。
如果您保留问题中提供的代码完全相同,除了将x
和y
的值替换为带有非原始值(如数组)的ClassTwo
构造函数,那么属性将按预期反映,如本答案的底部所示。这证明了原因与堆内存中单独对象的实例化无关,而只是所用参数类型的结果。
基元和非基元之间的区别在于基元是按值传递的,而非基元是通过引用传递的。因此,将基元分配给另一个变量或属性会导致复制值而不是引用它。
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] );
}