JavaScript函数里面的新对象

时间:2017-09-09 11:20:24

标签: javascript oop

我在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 ......

5 个答案:

答案 0 :(得分:2)

当您使用Object创建new时,它会在heap中分配单独的内存。因此,语句this.position = new ClassOne( this.x, this.y );this.position分配新内存,现在this.position.xthis.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.xnewObj.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完全忽略了这一点。这与newObjnewObj.position是独立的对象无关,而与xy是原始值的事实有关。

如果您保留问题中提供的代码完全相同,除了将xy的值替换为带有非原始值(如数组)的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] );
}