最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Why is Javascript object reference not updated? - Stack Overflow

programmeradmin3浏览0评论

I'm creating a bunch of objects and I want to use some of the objects in others, so I'm passing them in so I can update them later. I'd expect to hold a reference to each object, but if I pass an object before it's created, it stays undefined even after I create it. Here's the code:

this.screen = new BatchScreen(screenList);
this.fieldData = new FieldData(this.screen, this.nutrientData);
this.nutrientData = new NutrientData(this.screen, this.fieldData);

function FieldData(screen, nutrientData)
{
    this.nutrientData = nutrientData;
}

this.fieldData.nutrientData is "undefined", which I don't understand as I thought this.fieldData holds a reference to this.nutrientData, which I create after it's assigned in this.fieldData.

I'm creating a bunch of objects and I want to use some of the objects in others, so I'm passing them in so I can update them later. I'd expect to hold a reference to each object, but if I pass an object before it's created, it stays undefined even after I create it. Here's the code:

this.screen = new BatchScreen(screenList);
this.fieldData = new FieldData(this.screen, this.nutrientData);
this.nutrientData = new NutrientData(this.screen, this.fieldData);

function FieldData(screen, nutrientData)
{
    this.nutrientData = nutrientData;
}

this.fieldData.nutrientData is "undefined", which I don't understand as I thought this.fieldData holds a reference to this.nutrientData, which I create after it's assigned in this.fieldData.

Share Improve this question asked Jan 13, 2015 at 23:06 christian.stockchristian.stock 2013 silver badges15 bronze badges 8
  • possible duplicate of this inside function – PM 77-1 Commented Jan 13, 2015 at 23:09
  • 3 How do you "pass an object before it's created"? – RobG Commented Jan 13, 2015 at 23:15
  • @RobG - obviously you just use jQuery and delegate the dropping to a parent object. – adeneo Commented Jan 13, 2015 at 23:18
  • 1 @adeneo—ah, must be part of the new crystal ball plugin. – RobG Commented Jan 13, 2015 at 23:21
  • @RobG - I was being lazy, I could set this.nutrientData = null first, which would work in any other language, but to Javascript it's the same in this context. – christian.stock Commented Jan 13, 2015 at 23:24
 |  Show 3 more ments

3 Answers 3

Reset to default 4

Short: you are not passing references.

Long: the evaluation strategy in JS is something called Call by sharing. It also is explained as "references passed by values".

What it means in details is that - in your

this.fieldData = new FieldData(this.screen, this.nutrientData);

statement the this.screen holds a reference, so it's passed by value. And the this.nutrientData holds nothing - so undefined is passed.

Then when you run

this.nutrientData = new NutrientData(this.screen, this.fieldData);

statement the this.nutrientData is being defined as a reference to a new object. But it's too late - we have already passed the undefined in the FieldData constructor.

So the best way to understand it - is to always think that the data is always passed by values, but sometimes those values keep references.

For your code to work as you expect the self.nutrientData and others must be pointers, which JS does not support in any way.

The solution:

if you have 2 mutially dependent objects then you cannot have both in their own constructors. One of them just have to expose additional setter and accept the dependency through it.

Not an answer but a possible solution. You really need a getter but support isn't sufficiently widespread. If you have interdependent properties, you can implement a getter for one (or perhaps both for consistency) so you have:

this.screen = new BatchScreen(screenList);

// Don't bother passing this.nutrientData since you know it's not defined yet,
// pass in the object that you want the nutrientData property of
this.fieldData = new FieldData(this.screen, this);
this.nutrientData = new NutrientData(this.screen, this.fieldData);

// In here, use a function to return the property so its read when called, 
// not when defined
function FieldData(screen, obj) {
    this.getNutrientData = function () {return obj.nutrientData};
}

Then instead of:

var foo = someInstance.fieldData.nutrientData;

use:

var foo = someInstance.fieldData.getNutrientData();

But there seems to be a circular relationship between fieldData and nutrientData.

In this case, this.nutrientData in the second line, is not being passed as a reference, since no reference to an object exists (at that point there is no this.nutrientData, so you are literally passing undefined).

I'd guess you are also having scope issues with this;

Try this (no pun intended):

var self = this;
this.screen = new BatchScreen(screenList);
this.fieldData = new FieldData(self.screen, new NutrientData(self.screen, self.fieldData));
// assumes that the nutrientData property exists from the object passed into FieldData
this.nutrientData = this.fieldData.nutrientData;
function FieldData(screen, nutrientData)
{
    this.nutrientData = nutrientData;
}
发布评论

评论列表(0)

  1. 暂无评论