2

I am trying to duplicate private prototype methods in javascript and found this bit of code, but I do not fully understand how it implements itself.

The code is...

var Foo = function () {};  

Foo.prototype = (function () {  

    // Private attributes  
    var somePrivateAttribute = 'Hello world';  

    // Private methods  
    function somePrivateMethod(val) {  
        alert(val);  
    }  

    // Public attributes and methods  
    return {  
        somePublicMethod: function () {  
            somePrivateMethod(somePrivateAttribute);  
        }  
    };  
})(); 

What I do not understand is when this object is initiated new Foo() does that create a new object for the prototype every time as it is in a self executing function? Could anyone please explain the benefits and disadvantages of using this for a project of mine.

How would this type of pattern work for objects that could have 500 instances or just 1. I am trying to understand and would greatly appreciate if anyone could enlighten me?

Is there any performance benefits to using this method?

user2251919
  • 665
  • 2
  • 11
  • 23
  • Performance benefits - compared against what? – Bergi Apr 14 '13 at 23:27
  • When I first started learning javascript I always used to assign functions to the prototype like `Name.prototype.function = `, what I was getting at was I didn't understand how the anonymous function was assigning the variables, I thought it would run everytime it was called, but your answer already answers that. – user2251919 Apr 14 '13 at 23:35

3 Answers3

3

What I do not understand is when this object is initiated new Foo() does that create a new object for the prototype every time as it is in a self executing function?

No. That's the point of prototypes, they are not duplicated - every of your Foo instances will inherit from the same Foo.prototype object.

Could anyone please explain the benefits and disadvantages of using this for a project of mine.

It looks like you're having a little misunderstanding, regarding the naming: Those "private" things are no "attributes" or "methods", as they have absolutely nothing to do with instance objects. They are just local variables which are only accessible from the functions you assign to the prototype object.

You might want to read How do JavaScript closures work? and their use in IIFEs.

How would this type of pattern work for objects that could have 500 instances or just 1.

It's perfectly fine. However, using the constructor pattern for just 1 instance might be a little odd - singletons can be defined in a simpler way.

If you want to read more on that pattern, search for revealing prototype pattern - it's the revealing module pattern applied to create prototype objects.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
2

I haven't seen that pattern before, using a module (that's what it's called) for the prototype... but here's what I'd recommend; it's similar but the module encloses everything:

var Foo = (function FooClass() {

  var privateVar = 'Hello world';  

  function privateFunc() {
    ...
  }

  function Foo() {}

  Foo.prototype = {
    publicMethod: function() {
      ...
    }
  };

  return Foo;

}());

var foo = new Foo();

What I do not understand is when this object is initiated new Foo() does that create a new object for the prototype every time as it is in a self executing function?

The self executing function runs once, returns the object, and it won't run again; it keeps a reference to the variables via closure.

elclanrs
  • 92,861
  • 21
  • 134
  • 171
  • So just to clarify, on script run time every bit of code in a self executing function is run, so in your code when `var Foo = ....` is read by the engine it is assigned a value `return Foo`? Thanks for your answer. – user2251919 Apr 14 '13 at 23:24
  • I have mixed feelings about this pattern. It's neat because it bundles everything together, but it also creates a lot of unused (and therefore unnecessary) closures. – RobG Apr 14 '13 at 23:36
0

What I do not understand is when this object is initiated new Foo() does that create a new object for the prototype every time as it is in a self executing function?

No, the assignment to Foo's prototype only happens once. Nothing wrong with it at all, just a little unconventional.

You could also write it like this (also unconventional, but accomplishes the same thing):

var Foo = function () {};  

Foo.prototype = new function() {  

    // Private attributes  
    var somePrivateAttribute = 'Hello world';  

    // Private methods  
    function somePrivateMethod(val) {  
        alert(val);  
    }  

    // Public attributes and methods  

    this.constructor = Foo;

    this.somePublicMethod = function () {  
        somePrivateMethod(somePrivateAttribute);  
    }  
}; 

As Bergi pointed out, this adds an extra object to the prototype chain; if you want to avoid that, you can write it like this instead:

var Foo = function () {};  

(function() {  

    // Private attributes  
    var somePrivateAttribute = 'Hello world';  

    // Private methods  
    function somePrivateMethod(val) {  
        alert(val);  
    }  

    // Public attributes and methods  

    this.somePublicMethod = function () {  
        somePrivateMethod(somePrivateAttribute);  
    }

}).call(Foo.prototype) 

By modifying the prototype instead of replacing it, the constructor property also stays intact.

Dagg Nabbit
  • 75,346
  • 19
  • 113
  • 141
  • Nooo! [Do not use `new` for IEFEs!](http://stackoverflow.com/q/10406552/1048572) Or do you want to create a second `new Foo.prototype.constructor()`? – Bergi Apr 14 '13 at 23:51
  • @Bergi, why not? The constructor usually isn't a big deal, but if you want it for type checking or something, it's easy to keep it intact... I'll edit it in. I'm not sure I understand your opposition to new-ing an IIFE, what's your point (other than the constructor)? Is it just stylistic? – Dagg Nabbit Apr 15 '13 at 06:56
  • Also the thing you linked has no relevance here... we're not talking about whether something's "static," we're assigning a value to a function's `prototype` property. This code has the exact same result as the OP's code (at least it did until I added `constructor` just now), the only difference is stylistic. The idea was to present a different way of looking at it. – Dagg Nabbit Apr 15 '13 at 07:03
  • It creates an additional, absolutely useless prototype object from which `Foo.prototype` inherits - and which so you very easily miss. Also, the anonymous function for the IEFE is no more anonymous really - it leaks into `Object.getPrototypeOf(Foo.prototype).constructor`. Shadowing that property as you do in your edit is not much helpful either. – Bergi Apr 15 '13 at 07:06
  • Well, the prototype object of that function is useless in this particular example, but if you take the concept further it can actually be pretty useful (putting utility methods in there for inheritance, for example). And who cares about things leaking into an anonymous throw-away object? But you're right, this does add one additional thing to the prototype chain. I like to use it for stuff, I've never noticed a hit to performance or anything like that. – Dagg Nabbit Apr 15 '13 at 07:08
  • The problem is that it is *not* thrown away - as you would have expected from the IEFE function. And no, that prototype is hardly useful - why not put things directly on `Foo.prototype`, the only object inheriting from it? The additional level of inheritance just makes it slower. – Bergi Apr 15 '13 at 07:14
  • @Bergi it's useful if you use a helper function to call it. Basically gives you functionality similar to `dojo.declare` (I know, dojo sucks). http://gitbuh.github.io/decl/ – Dagg Nabbit Apr 15 '13 at 07:24
  • Yeah, change it to `function() {…}).call(Foo.prototype)` and everything is fine :-) – Bergi Apr 15 '13 at 07:29