Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Would this be a good way to do private functions?

Tags:

javascript

Just saw some interesting code while doing a typo in coffee-script. I got the following code

var Mamal, mam;

Mamal = (function() {
  var __priv_func;

  function Mamal() {}

  Mamal.prototype.simple_var = 5;

  Mamal.prototype.test = function() {
    return __priv_func(this);
  };

  __priv_func = function(instance) {
    return alert(instance.simple_var);
  };

  return Mamal;

})();

mam = new Mamal();
mam.simple_var = 10;
mam.test();

Now I've read alot about the module pattern in javascript and why its a bad thing (takes more memory, longer to create...) but of course the upside is having truly private functions/variables. Wouldn't the above code be a good way to create private functions (this wouldn't work for variables, unless you wanted static private variables) as the function is only created once in the closure?

One of the upsides of the module pattern is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?

like image 279
Robin Heggelund Hansen Avatar asked Dec 08 '11 04:12

Robin Heggelund Hansen


People also ask

Should functions be public or private?

You should make a function private when you don't need other objects or classes to access the function, when you'll be invoking it from within the class. Stick to the principle of least privilege, only allow access to variables/functions that are absolutely necessary.

What is the point of private functions?

Private methods are useful for breaking tasks up into smaller parts, or for preventing duplication of code which is needed often by other methods in a class, but should not be called outside of that class.

Why should certain functions be private and others public?

So what's the difference between a public and private function? A private function can only be used inside of it's parent function or module. A public function can be used inside or outside of it. Public functions can call private functions inside them, however, since they typically share the same scope.

Is it good to practice to unit test private methods?

Unit Tests Should Only Test Public Methods The short answer is that you shouldn't test private methods directly, but only their effects on the public methods that call them. Unit tests are clients of the object under test, much like the other classes in the code that are dependent on the object.


1 Answers

To highlight the points I was making, because clearly there was more to the question than just the title:

  • Yes a module pattern is a good and commonly used way to create private (er, local) data (functions or whatever), and export some sort of interface. Since a function is the only way to create variable scope, it's the only way to create private functions.

  • Because the functions will be shared by all objects created from Mamal, they're not useful for a functional inheritance pattern (references to functional inheritance have been removed from the question).

  • There's no performance improvement over lookups in the prototype chain, because the prototype chain needs to be traversed anyway just to get to your private functions.


To address specific questions points in the updated post:

"Would this be a good way to do private functions?"

Sure, but that's because having a function nested in another is the only way to scope a function.

"Now I've read alot about the module pattern in javascript and why its a bad thing..."

For a one-time use module, I don't see any issue. Also, any data referenced by variables that are no longer needed after the module function exits is free for garbage collection. This wouldn't be the case if they were global, unless you nullified them.

"...of course the upside is having truly private functions/variables..."

Yes, though some would take exception to the use of the word "private". Probably "local" is a better word.

"...this wouldn't work for variables, unless you wanted static private variables..."

Yes, though again some may take exception to the use of the word "static".

"Wouldn't the above code be a good way to create private functions...as the function is only created once in the closure?"

Yes again, nested functions are the only way to make them "private" or rather local.

But yes, as long as the function only ever needs to access the public properties of the objects (which are accessible to any code that can access the object) and not local variables of the constructor, then you should only create those functions once, whether or not you use a module pattern.

"One of the upsides of the module pattern is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?"

No, you haven't exported your private functions directly, but rather the only way to call them is by traversing the prototype chain.

But if you ditched the prototype chain, and added functions as properties directly on the objects created, then you'd have some improvement there.

Here's an example:

Mamal = (function() {
  var __priv_func;

  function Mamal() {
    this.test = __priv_func;
  }

  Mamal.prototype.simple_var = 5;

  __priv_func = function() {
    return alert( this.simple_var );
  };

  return Mamal;

})();

Now you've eliminated the prototype chain in the lookup of the test function, and also the wrapped function call, and you're still reusing the __priv_func.

The only thing left that is prototyped is the simple_var, and you could bring that directly onto the object too, but that'll happen anyway when you try to modify its value, so you might as well leave it there.


Original answer:

If you're talking about a module pattern, where you set up a bunch of code in (typically) an IIFE, then export methods that have access to the variables in the anonymous function, then yes, it's a good approach, and is pretty common.

var MyNamespace = (function () {
    // do a bunch of stuff to set up functionality
    //    without pollution global namespace

    var _exports = {};

    _exports.aFunction = function() { ... };
    _exports.anotherFunction = function() { ... };

    return _exports;
})();

MyNamespace.aFunction();

But in your example, I don't see and advantage over a typical constructor, unless you decide to use the module pattern as above.

The way it stands right now, the identical functionality can be accomplished like this without any more global pollution, and without the wrapped function:

var Mamal, mam;

Mamal = function() {};

Mamal.prototype.test = function() {
    return console.log(this.simple_var);
};

Mamal.prototype.simple_var = 5;

mam = new Mamal();
mam.simple_var = 10;
mam.test();

" Wouldn't the above code be a good way to create private functions (this wouldn't work for variables, unless you wanted static private variables) as the function is only created once in the closure?"

Given the rewritten code above, the function is still only created once. The prototype object is shared between objects created from the constructor, so it too is only created once.

"One of the upsides of functional inheritance is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?"

In your code, the function is called via a function in the prototype chain, so it has that same overhead, plus the overhead of finding the local function in the variable scope and invoking that function as well.

So two lookups and two function invocation instead of one lookup and one invocation.

like image 57
RightSaidFred Avatar answered Sep 29 '22 22:09

RightSaidFred