0

For a project I'm working on, I'm building some data objects with the following lay-out (it's a binary file that I'm reading with ArrayBuffers:

AFile.prototype = {
    p: new BufferPack(),
    filedata: null,
    position: 0,
    label_records: null,
    closestmultipleof: function(n,v) {
        return Math.ceil((v / n) * n);
    },
    r: function(size) {
        result = new Uint8Array(this.filedata,this.position,size);
        this.position += size;
        return result;
    }
    readValueLabel: function() {
        return {
            value: this.rS(8),
            len: this.rS8(),
            label: this.rS(this.closestmultipleof(8, this.len + 1))
        };
    },
    readLabelRecords: function() {
        return {
            rec_type: this.rS32(),
            label_count: this.rS32(),
            value_labels: _.map(_.range(this.label_count), function(num) {
                console.debug(num);
            },this)
        };
    },
    loadFile: function(blob) {
        this.filedata = blob;
        this.label_records = this.readLabelRecords();
    }
};

However, I seem to have problems with accessing the values in the return scope. In some return scopes, I need to access the variables from the same scope in order to manipulate the data a little bit (see the definition of value_labels).

Only, it doesn't seem to be able to access the variable label_count there (probably because it is in the same return scope). How would I be able to do this?

The only way that I can get it to work is if I do this:

ret = {}
ret['a'] = 5;
ret['b'] = ret['a'] * 2
return ret;

But that seems ugly enough. Any ideas?

And yes, it is a singleton! I'm only going to use this once.

Let me make clear: The problem is within the following code:

return {
   a: functionreturn(),
   b: this.a * s
};

This.a doesn't seem to exist there.

Mats Willemsen
  • 815
  • 1
  • 9
  • 25
  • If I read the question correctly, it boils down to how access a property of an object literal from within this literal. There is no (good) way. See e.g. http://stackoverflow.com/questions/3173610/can-a-javascript-object-property-refer-to-another-property-of-the-same-object. – georg Jun 19 '13 at 06:58
  • Why are you putting properties inside the prototype? You'd want to put those in the constructor so they're unique to the instance right? Or is this a singleton? – elclanrs Jun 19 '13 at 07:01
  • Where are the rS.. functions defined? If they are defined on `AFile.prototype.rS..=function()...` then you are overwriting it with the code you posted. If it's declared as this.rS... then you're creating the rS.. property for each instance of AFile even though the rS.. functions are exactly the same and do exactly the same thing. – HMR Jun 19 '13 at 07:05
  • I've added an answer because I'm curious as how you solved it by setting `me=this`. The code you posted doesn't need it as far as I can see. The answer added is to re produce the problem with the least possible code. – HMR Jun 19 '13 at 07:30
  • Yeah, I don't think I need it as well. My problems aren't really with the 'this' scope, but I want to access the values from within the return{} scope. – Mats Willemsen Jun 19 '13 at 07:33
  • @MatsWillemsen I guess you solved the problem. Sorry for not understanding what the problem actually is as I can't see it in the posted code. I'm sure you are aware of `this` can change when you pass the funtion as an argument for a callback (like setTimeout setInterval or an event handler). – HMR Jun 19 '13 at 07:38
  • I didn't solve the problem, though! I still can't access variables from my return scope. It's pretty vital for a 'neat' organisation of my object declaration. And yes, I'm aware of that. Which is why I use the Underscore context parameters on my other functions. – Mats Willemsen Jun 19 '13 at 07:40
  • I get it, you want to access `label_count` but it's declared and value is set within the same object literal as where you want to read it:{label_count:22,double_label_count:???*2}. You want to cache the value of `label_count` so you don't have to keep calling rS32(). I have updated my answer, instead of creating a `closure` value to this you can create a closure with the label_count value. – HMR Jun 19 '13 at 07:44

2 Answers2

1

[update] You can create a closure to label_count.

function AFile(){};
AFile.prototype ={
    readLabelRecords: function() {
        label_count=this.rS32();
        return {
            label_count:label_count,
            log:console.log(label_count)//'return from rs32'
        };
    },
};
AFile.prototype.rS32=function(){
  return "return from rs32";
}
var o = new AFile();
o.readLabelRecords();

That answer was based on the code provided, the simplest code to re produce:

function complicatedCalculations(){
  return 22;
}
function returnObject(){
  var cacheComplicated=complicatedCalculations();//closure variable will
         // be available within the entire body of returnObject function
         // but never outside of it.
  return{
     calculated:cacheComplicated,
     twiceCalculated:cacheComplicated*2//you could not access calculated
                           // here so using a cache closure variable
  }
}

Or have your returnObject function return a new instance of an object created with a constructor function:

function returnObject(){
  return new (function(){
    this.calculated=complicatedCalculations();
    this.twiceCalculated=this.calculated*2;
  })();
}
HMR
  • 37,593
  • 24
  • 91
  • 160
  • Perfect! This seems to work. It feels a bit weird to have to declare all variables two times, but it could be worse! – Mats Willemsen Jun 19 '13 at 07:50
  • You could `return new (function(){this.label_count=22;this.double_label_count=this.label_count*2;})();` No need to declare the variables twice. – HMR Jun 19 '13 at 07:58
  • @MatsWillemsen updated my answer to return an object instance created with a constructor function. No need to double declare variables used in the same object. – HMR Jun 19 '13 at 08:07
  • YES. This is the way to go! This is beautiful! Sublime Text states it is a 'weird construction', but I'll just ignore that for now. Perfect! – Mats Willemsen Jun 19 '13 at 08:10
0

You forgot a comma before readValueLabel which makes the structure is invalid.

Update:

Too bad that the other answer was deleted, it had a valid point even if it didn't "compile". Reference to this is problematic inside inner scopes in JS, but it can be worked around by doing something like that:

readLabelRecords: function() {
        var that = this;
        return {
            rec_type: that.rS32(),
            label_count: that.rS32(),
            value_labels: _.map(_.range(that.label_count), function(num) {
                console.debug(num);
            },that)
        };
    }
Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129