7

Suppose I create an object factory like so:

var newObj=function(x){
  var obj=[]
  obj.x=x
  obj.add=function(n){
    return this.x+n
  }
  return obj
}

Now suppose I create hundreds of instances of this object:

var obj1=newObj(1)
var obj2=newObj(2)
...

Does each obj1,obj2,... store their own copy of obj.add or do they all contain a reference to a single instance of obj.add stored in memory?

Thanks!

gloo
  • 2,490
  • 3
  • 22
  • 38
  • I am creating a node application with a very large number of very large objects using the factory technique shown above. It occurred to me that I am probably wasting a lot of storage space. It seems I should start filling the prototype property instead. – gloo Jul 07 '13 at 16:09
  • You could have found out easily by comparing `obj1.add === obj2.add`. – Felix Kling Jul 07 '13 at 18:09
  • See http://stackoverflow.com/questions/17308446/how-big-are-javascript-function-objects – user123444555621 Jul 07 '13 at 19:49

2 Answers2

2

Both obj and obj2 will instantiate their own copies of obj.add. They are function expressions that get executed at creation and stored in memory for the duration of the object's lifetime.

If you want to maintain performance, what you should use is prototyping:

var newObj=function(x){
  this.obj = [];
  this.obj.x = x;
  return this.obj;
}

newObj.prototype.add = function(n) {
    return this.obj.x += n;
}

This will create a function that all future newObj objects will use without taking up extra space in memory for the exact same function.

Way Spurr-Chen
  • 405
  • 2
  • 9
  • 2
    Point of using prototypes is lost if you declare the method _both_ on the prototype and in the function as before, as the latter will override the prototype definition – altschuler Jul 07 '13 at 15:56
  • Thanks for that catch; I've updated my answer to not be so silly. – Way Spurr-Chen Jul 07 '13 at 15:59
  • Thanks. In order for prototyping to work must I use the 'new' keyword technique as in 'new Obj' or does this work with my 'newObj' factory? – gloo Jul 07 '13 at 16:01
  • A prototype can be bound to any JavaScript object, so as long as you can reference it, you can create it. It's generally advisable to stay away from the `new` declaration entirely because it can be confusing. What I usually do is something like: `function factory(x) { // do stuff } factory.prototype.add = function(n) { // do more stuff }` and then just create new objects from what my function returns whenever I need it. – Way Spurr-Chen Jul 07 '13 at 16:04
  • *"It's generally advisable to stay away from the `new` declaration entirely because it can be confusing."* Not at all. There is *nothing* that speaks against using `new` (only maybe if one doesn't know how it works). I also believe the code in your answer is incorrect. Why do you *return* `obj.add`? An array does not have an `add` method, i.e. you are returning `undefined`. Please provide an example of how you would create objects from that function now. – Felix Kling Jul 07 '13 at 18:07
  • 1
    But `obj` is an array and arrays don't have an `add` method. Adding `add` to `newObj.prototype` does not make the array have that function. – Felix Kling Jul 07 '13 at 20:16
1

They will all have their own instances of that method.

If you use prototypes, they will share that method, given you declare it on the prototype object.

So you could do something like

newObj.prototype.add = function(n) {
    return this.x+n
}

And then not declare add on the object as before.

In V8 there is a thing called hidden classes which basically means that all newObj instances will share a hidden class as long as you don't make changes to an instance, which would (as far as I understand) effectively make all the newObj's share the method as with prototyping.

altschuler
  • 3,694
  • 2
  • 28
  • 55