0

I'm currently researching a way to protect JavaScript functions as private, exception will be thrown if the caller is invalid. Then I have a problem here: If a closure is defined inside a valid caller, is it a way to get the valid caller from the inner closure?

For example:

function validCaller() {
    var self = this;
    self.privateFunction1();
    $.each([/*...*/], function (key, val) {
        self.privateFunction2(); 
    });
}

And, of course, privateFunction1 will get the caller validCaller correctly, but privateFunction2 will get the anonymous function as caller, so the access will be denied.

It is not the right way if I get validCaller from the call stack by expression caller.caller.caller, because I can't determine how many levels should I trace back, and, in some special cases, the anonymous function needs to be called outside of validCaller.

Maybe I asked the question in a complicated way, the simple way is:

how can I capture a function's scope chain?

Knly
  • 9
  • 3
  • Instead of reinventing the wheel, you should use the [module pattern](http://www.yuiblog.com/blog/2007/06/12/module-pattern/). Using `caller` won't do the trick, since you may run into a circle: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/Caller#Notes – user123444555621 Jul 20 '12 at 06:05

1 Answers1

1

The reasonable way to keep something private is just not to tell anyone about it...

function MyObject(a, b, c)
{
    this.a = a;
    this.b = b;
    this.c = c;

    // Note: NOT using this.private1 = function() { ... }
    function private1()
    {
       ...
    }

    function private2()
    {
       ...
    }

    // Public methods
    this.public1 = function()
    {
       ...
       private1(); // Note; not using "this." in the call
       ...
       private2();
    }
 }

With this approach not only no one except the methods of MyObject will be able to call private1 and private2... but others would not even be able to find those names and there will be no risk of an accidental name collision.

You can use the same approach for private data members. Just declare them as simple local variables var x; in the constructor and don't use this.x syntax for access them but just x. As for the methods no one will be able to access them and there will be no risk of even inadvertent overwriting.

If you really want a runtime check to prevent unauthorized functions to call your methods you can use sort of a "security token".

function MyObject()
{
   var authorization = []; // An empty array will do

   this.private_method = function(auth) {
       if (auth !== authorization) throw "Unauthorized call";
       ...
   };

   this.public_method = function() {
       ...
       this.private_method(authorization);
       ...
   };
}

With this approach you can be sure even of which instance is calling the private method.

If you want instead this ability for any instance then make the constructor a closure itself that captures the authorization token from an enclosing scope.

PS: I don't know much context of why you want to do this in the first place, but sounds weird.

6502
  • 112,025
  • 15
  • 165
  • 265
  • Your 'public1' is predefined, so it's easy to access the hidden 'private1' and 'private2'; But I want my 'validCaller' to be given at RUNTIME, so the 'privateFunction1' and 'privateFunction2' mustn't be hidden. – Knly Jul 20 '12 at 06:58
  • @Knly: If valid callers can be added at run time, who says which caller is valid and which one is not? – 6502 Jul 20 '12 at 08:21
  • check this: define({name: 'ClassName', privates: {private1: function(){...}}, publics: {public1: function(){...}}}); – Knly Jul 20 '12 at 08:56