rabbit.aaron
rabbit.aaron

Reputation: 2579

One attempt of private methods in JS

I've seen people trying to attempt implementation of private methods in JS. However they all have different issues, like this one: JavaScript private methods

I believe my attempt has some problems as well. But other than the overhead and caller is not allowed in strict mode, what are the problems with my implementation? You can see an working example in jsfiddle: http://jsfiddle.net/rabbit_aaron/oqpen8c8/17/

the implementation is also pasted here:

var CLASS = function () {
    this.publicFunctions = {};
    this.PROTOTYPE = {};
    var _class = function () {
        this.constructor.apply(this, arguments);
    };
    _class.prototype = this.PROTOTYPE;
    _class.prototype.validateAccess = CLASS.prototype.validateAccess;
    _class.prototype.constructor = function () {};
    _class.prototype.publicFunctions = this.publicFunctions;
    this.finalClass = _class;

    return this;
};

CLASS.prototype.validateAccess = function (caller) {
    if (this.publicFunctions[caller] !== caller) {
        throw 'Accessing private functions from outside of the scope';
    }
    return true;
};
CLASS.prototype.setConstructor = function (func) {
    this.PROTOTYPE.constructor = func;
};
CLASS.prototype.addPrivateFunction = function (name, func) {
    this.PROTOTYPE[name] = function () {
        this.validateAccess(this[name].caller);
        func.apply(this, arguments);
    };
    return this;
};

CLASS.prototype.addPublicFunction = function (name, func) {
    this.PROTOTYPE[name] = func;
    this.publicFunctions[this.PROTOTYPE[name]] = this.PROTOTYPE[name];
    return this;
};


CLASS.prototype.getClass = function () {
    return this.finalClass;
};

Upvotes: 1

Views: 90

Answers (2)

Bergi
Bergi

Reputation: 664297

I believe my attempt has some problems as well.

Yes.

But other than the overhead and caller is not allowed in strict mode

I wouldn't call that a problem, I'd call it a no-go. Strict mode is supposed to be the default mode.

what are the problems with my implementation?

About your approach of making methods "private":

  • It's easy to circumvent your measures. Like @Austion you can simply override the validateAccess function, but you can also mess with the public publicFunctions object
  • It's only hiding methods, not fields. Making non-function properties private is often the more relevant goal, as these are containing the (protection-deserving) state of the instance.
  • It doesn't work in engines that have no Function::toString decompilation (there are a few old ones). Also, it doesn't work for methods that are programmatically created (as closures) and share the same body.

A few bugs in your implementation that are possible to fix:

  • private methods can't return a value
  • private methods can't call other private methods, only public methods can call them
  • this.constructor.apply(this, arguments); is a nice idea to make a settable constructor. However, it a) will fail horribly once you try inheritance (can be fixed by by calling _class.prototype.constructor) and b) corrupts the rule of thumb that fn.prototype.constructor == fn/Object.getPrototypeOf(instance)==instance.constructor.prototype

Remember, true privacy is only possible through the use of closures.

Upvotes: 0

Austin
Austin

Reputation: 3318

The first thing that comes to mind is that it is pretty simple to do the following in some code that gets loaded later on:

instanceOfSubClass.validateAccess = function (caller) {
    return true;
}

This effectively overrides validation. Pretty much all private variable tricks that don't involve using nested scoping to hide variables suffer from this problem. Of course, this is a pretty specific thing to have to know to do, so it depends on what you are trying to protect against. If you just want to protect against yourself in the future, then this might work fine, but if you are publishing a library that will be interacting with code you don't write and you want to ensure that it will always behave properly, then this isn't the way to go.

Upvotes: 1

Related Questions