is there a way to inject privileged methods after an object is constructed?

Go To StackoverFlow.com

4

I'm trying to write fully automated unit tests in JavaScript and I'm looking for a way to read some private variables in various JS functions. I thought I recalled a way to inject privileged members into a function/object (and found an overwhelming occurrence of "no such thing as private in JS") and yet I can't find any resources indicating how.

I'm trying to read through the properties of .prototype but if there's a way, someone out here would know where to direct me faster than I'd find on my own.

Thanks

Update

  1. Privileged means a function that is usable from outside an object and has access to read "private" variables (variables otherwise unable to read from outside). See http://javascript.crockford.com/private.html for Crockford's explanations.

  2. A sample of the function I'm trying to inject to is o2, where I need to validate the value of x (this is a simplified example, the actual code does some transformations and sends them off to other functions which I plan on testing separately).

    var o2 = function() {
        var x = 'me';
    };
    

Update 2: Thanks to everyone who's taken the time to respond. I'm seeing that the overwhelming response here is, "private is private" despite the commentary I see in other SA questions where people say "nothing in JS is private". I guess that is more like rhetorical commentary rather than what I was hoping was some kind of insight into a potential loophole I didn't yet know about.

2012-04-04 22:57
by patrickgamer
do you have a sample of your code? as far as i know, when using purely prototype, there is no such thing as "private" - Joseph 2012-04-04 23:02
private is really something that doesn't exist in Javascript. What does exist are local function closure variables that can be best described as private variables of the function closure because you can't see them outside of the closure. But what do you mean by privileged member is a mystery to me - Robert Koritnik 2012-04-04 23:02
@RobertKoritnik i think what he meant by priveledged are "getters and setters", public methods that have and/or give access to private properties and methods - Joseph 2012-04-04 23:03
@RobertKoritnik I've linked to the definitions I use around private/public/privileged. Hope that helps clarify - patrickgamer 2012-04-04 23:35
the whole idea of private is to have properties not readable from the outside without help from predefined privileged methods. if you plan to inject code that made private visible, or made this procedure possible, might as well make them all properties public! what's the use setting them private when they are injectable - Joseph 2012-04-04 23:54
@Joseph the point is that testing methods shouldn't dictate software architecture. I'm just trying to see if there's a work-around to make my testing life easier, not redesign the code base I'm testing - patrickgamer 2012-04-05 19:26


3

Correct answer to your question

Even if we try to help you as much as we can, the correct answer to your question is simple:

...you can't

What good would closure variables be if we could access them directly from outside of closure?

if you had an object with private variables, they wouldn't be accessible outside function closure, which is the constructor function.

var c = function() {
    var priv = "private";
    this.get = function() {
        return priv;
    };
}

var o = new c();
o.injected = function() {
    return priv; // ERROR!!!!!! priv doesn't exist in function scope
};

It is of course different matter if you enclose the whole thing inside a function closure but then you wouldn't have object privates, but rather function closure internals that would be shared among all prototypes within this closure.

(function(){

    var intrn = "internal";

    // omit "var" to make it global
    c = function() {
        this.get = function() {
            return intrn;
        };
    };

    // omit "var" to make it global
    o = new c();
    o.injected = function() {
        return intrn; // WORKS
    };
})();

o.injected();

but this is different than object privates...

2012-04-05 14:10
by Robert Koritnik
Thanks for taking the time to consider the question - patrickgamer 2012-04-05 19:28
+1 for pointing out the issue that "privacy won't be privacy if someone can peek through" and the "internals" - which would be the right thing to do if you want to see the inside but not be affected by the outside - Joseph 2012-04-05 21:52


1

Know that I am quite late to the party, but yes it is possible. Although AFAIK it requires use of eval() and a helper method:

function foo(){
    var a = 'a';
    this.addMethod = function(prop, val){
        this[prop] = eval('(' + val.toString() + ')');
    }
}
var bar = new foo();
bar.b = 'b';
var Fn = function(){return a + this.b}
bar.addMethod('getValue', Fn);
bar.getValue(); //yields 'ab'

You can use eval() in this case to redefine the function within the context of the closure. However, using eval() is dangerous, ESPECIALLY don't eval() any user input, EVER. However, for use in a testing suite/script it should be fine.

2014-06-19 15:56
by Jared Smith


0

I'd suggest you read Crockford's treatise on how to achieve privileged and private in javascript objects.

If by privileged, you mean methods that are not accessible outside the object, but are callable by other methods and are actually methods on the object, then there really isn't any way to do that because one you put a method on the object, javascript let's anyone call it.

If you just wanted to add a function that was only callable by methods, you could do that by having a private member variable (see how Crockford implements that) that was an object and you could put the methods on that object. Then all existing methods (implemented the way Crockford suggests in the constructor to have access to the private member data) could call those methods. They would technically be members of a different object, but could be given private access to your object's instance data if needed.

It's all pretty convoluted so you'd probably get a better answer if you described the problem you're really trying to solve.

2012-04-04 23:23
by jfriend00
thanks. I've read it and that only helps in defining privileged methods inside the constructor (i.e. when the object is defined). That doesn't help in my case, where we aren't looking to add testing code permanently within our solution. Ideally, the tests should be ran on the page (in console or using greasemonkey) after loading a page - and thus after the constructor is ran - patrickgamer 2012-04-04 23:38
You will have to show the exact code you are working with and what data you want this newly added method to have access to for us to know what options you have. You can add regular methods anytime. What exact data are you trying to get access to? You cannot add new methods that get access to private data trapped inside a closure unless there is an existing method that provides access to that data (then it isn't really private data). Private means private - jfriend00 2012-04-04 23:47


0

I don't think you can do that. Consider the following code:

function foo() {
    var privateVar = 10;            
    this.privilegedMethod = function() {
         return privateVar;   
    }
}
var obj = new foo();

Here, privilegedMethod has access to privateVar, since it's part of the closure created when the method was defined. Of course, you can always attach a new method to the object after instantiation:

obj.newMethod = function() { return "hello" };
alert(obj.newMethod()); // alerts "hello"

But this new method won't have access to privateVar.

2012-04-04 23:23
by bfavaretto
Ads