2

I have an object in Javascript and want to process the data passed into the constructor using a function that could later be called externally with more data. Naturally I don't want to duplicate the code (once in the constructor, once in a function), so how should I best set this up?

I could use a nested function, but I'm told this is inefficient:

function MyOb(data) {
    this.myData = {};
    function addData(newData) {
        //Add newData to myData
    }
    addData(data);
}

But if I use a prototype I get a "can't find variable addData" error on line 3:

function MyOb(data) {
    this.myData = {};
    addData(data);
}

MyOb.prototype.addData = function(newData) {
        //Add newData to myData
}

So am I forced to either use a nested function or repeat myself, or is there a way of making this work using prototype?

Matt Parkins
  • 24,208
  • 8
  • 50
  • 59
  • With your code `myData` is common to all instances of `myObj`. Is this the intention? If `myData` can be a property then things are simpler. – HBP Jun 17 '13 at 12:47
  • Yep! It's a generic property store with get, set, save, load functions that has multiple instansiations by different parts of a larger application. – Matt Parkins Jun 17 '13 at 14:17

3 Answers3

5

Change

function MyOb(data) {
    var myData;
    addData(data);
}

to

function MyOb(data) {
    this.myData = {}; // or another initialization
    this.addData(data);
}

You need the explicit this in JavaScript objects.

Note also that using var myData makes it private : you won't be able to use this variable from functions defined outside the constructor, including the addData function. That's why you probably need this.myData instead.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
1

Using the prototype you need to create a new object:

var abc = new MyOb(data);

then you can access the function using the this:

function MyOb(data) {
    var _myData; // local variable in this scope (addData won't have access)
    this.myData = {}; // public variable
    this.addData(data);
}

If you don't use the newto build your object, then the thiswill be the window, and your code won't work

fmsf
  • 36,317
  • 49
  • 147
  • 195
1

You should just make the nested function publically available as a property on your object:

function MyOb(data) {
    var myData;
    function addData(newData) {
        //Add newData to myData
    }
    addData(data);
    this.addData = addData;
}

Your current code with the prototype suffers from the problem that you're trying to get the function like a variable, while it's a (inherited) property of your instance (referenced by this). However, changing it to

    this.addData(data);

would lead to the error can't find variable myData in the prototype function - it's a variable that is local to the constructor. You would have to make that a instance property as well to use the prototype. See also Javascript: Do I need to put this.var for every variable in an object?.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thanks I've updated code in the question. Thanks for the link too. – Matt Parkins Jun 17 '13 at 14:23
  • 1
    Well, if it's a property anyway then you just have to call the prototype method with the `this.addData(data);`. If you need the full function code, look at dystroy's answer, I'm not gonna repeat it :-) – Bergi Jun 17 '13 at 14:28