0

I am essentially trying to set a function's prototype within the function itself. The purpose is to hide many functions inside one public function, yet keep the functionality.

Here is the non-working code in a jsFiddle. The intended behaviour is displaying "Greetings!" and "Take me to your leader."

The code can be 'fixed' by moving the Outer.prototype lines and the Extensions function out of the Outer function to the global scope. However, this means the Extensions function is public and free for direct use, which it shouldn't be.

What would be a good way to achieve this 'private' behaviour?

Kendall Frey
  • 43,130
  • 20
  • 110
  • 148

1 Answers1

1

This does not work because you are overriding the prototype. When you call new Outer, then this will inherit from the current Outer.prototype. You are then overriding Object.prototype inside the function, but it does not affect the currently created instance, only future ones.
You'd have to extend the existing prototype.

But if you want hide certain functions, use a self-invoking function:

var Outer = (function() {

    function Extensions() {
    }
    Extensions.protoype.Greet = function () {
        alert(this.Greetings);
    }

    function Inner() {
        Extensions.call(this);
        this.Greetings = "Take me to your leader.";
    }
    Inner.prototype = Object.create(Extensions.prototype);
    Inner.prototype.constructor = Inner;

    function Outer() {
        Extensions.call(this);
        this.Greetings = "Greetings!";
    }
    Outer.prototype = Object.create(Extensions.prototype);
    Outer.prototype.constructor = Outer;

    Outer.prototype.getInner = function() {
        return new Inner();
    };

    return Outer;

}());

Here, Extensions is defined inside the immediately executed function. Therefore it is not accessible from the outside. Only Outer can be accessed since you return it from that function.

See this answer for a very good explanation of inheritance done right in JavaScript.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Cool. What about the `Inner` function? The `Extensions.Greet` function must also be able to be called on an `Inner` object. – Kendall Frey Jun 25 '12 at 22:47
  • You can do it exactly the same way. Define it inside the closure and return a new instance from the `getInner` method. – Felix Kling Jun 25 '12 at 22:54
  • Could you add that to the code so I can see it? It's a little hard to see it in my mind's eye. Especially since I'm still trying to grok the fancy stuff like `call`. – Kendall Frey Jun 25 '12 at 22:58
  • Updated... `call` just sets `this` to the value you pass as first argument. See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/Call and https://developer.mozilla.org/en/JavaScript/Reference/Operators/this – Felix Kling Jun 25 '12 at 23:02
  • Yeah, I knew that, just hadn't seen it in action much. You gave me the idea of encapsulating everything into a function like you did, but without the extra closure stuff, just to hide the functions. Is that a bad idea? If so, why? – Kendall Frey Jun 25 '12 at 23:04
  • @Kendall: I don't understand what you mean... what should be a bad idea? – Felix Kling Jun 25 '12 at 23:07
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/13019/discussion-between-kendall-frey-and-felix-kling) – Kendall Frey Jun 25 '12 at 23:08