Accessing Private Member Variables from Prototype-Defined Functions

Accessing private member variables from prototype-defined functions

No, there's no way to do it. That would essentially be scoping in reverse.

Methods defined inside the constructor have access to private variables because all functions have access to the scope in which they were defined.

Methods defined on a prototype are not defined within the scope of the constructor, and will not have access to the constructor's local variables.

You can still have private variables, but if you want methods defined on the prototype to have access to them, you should define getters and setters on the this object, which the prototype methods (along with everything else) will have access to. For example:

function Person(name, secret) {
// public
this.name = name;

// private
var secret = secret;

// public methods have access to private members
this.setSecret = function(s) {
secret = s;
}

this.getSecret = function() {
return secret;
}
}

// Must use getters/setters
Person.prototype.spillSecret = function() { alert(this.getSecret()); };

Access private members in prototype functions

There's some fatal flaws with your design:

  • The prototype function is redefined each time the constructor is called.
  • All instances will share the same variable.

Redefining functions each time the constructor is called is unavoidable with privileged functions, but if you choose to go down that path, you would define the functions directly on this rather than the prototype.

function SomeObject() {
var privateVar = 'private value';

this.somePriviledgedFunction = function () {
//Use privateVar here
};
}

Now, with the support of WeakMap, there's a new pattern that would let you access private members from functions defined on the prototype. You would basically use an IIFE around your class declaration and have a shared WeakMap only visible within that scope to hold all private members. Object instances will be used as keys so that their values gets garbage collected when the objects are no longer around.

var SomeObject = (function (privates) {

function SomeObject(someValue) {
privates.set(this, {}); //initialze the privates scope
privates.get(this).privateVar = someValue;
}

Object.defineProperty(SomeObject.prototype, 'privateVar', {
get: function () {
return privates.get(this).privateVar;
}
});

return SomeObject;

})(new WeakMap());

var o1 = new SomeObject('first object');
var o2 = new SomeObject('second object');

o1.privateVar; //first object
o2.privateVar; //second object

However, note that every SomeObject's prototype functions that need access to private variables will have to be defined within the same module (within the surrounding IIFE). Another issue would be that other instances of a class could potentially steal other's privates if one is not careful with the design, but not from any function defined outside the IIFE, so that's no a real issue to me.

JavaScript: Private variables in prototype function

Functions associated with a prototype object have exactly the same sort of access to the object as any other function. Also, like other functions, they have no access to local variables that existed in the constructor function when it was called.

How to get private variables from prototyped methods in Javascript

This can be accomplished in ES 6, but I still think its largely unnecessary except at the module-level:

const Foo = (() => {
let privateData = new WeakMap();

return class {
constructor () {
privateData.set(this, {
hidden: 'bar'
});
}

// this is a prototype function, we could equivalently define
// it outside the class definition as Foo.prototype.getPrivate
// and it would be the same
getPrivate () {
return privateData.get(this).hidden;
}
}
})();

console.log(new Foo().getPrivate()); // logs 'bar'

Importance of the WeakMap:

It allows arbitrary objects as keys, but those keys are weakly held: they don't count as references to prevent the key object from being garbage collected. Once the class is returned, code outside the IIFE its defined in can't access privateData. See this for more info.

Note that this won't necessarily break inheritance depending on how you're doing it:

class Baz extends Foo {
constructor () {
super(); // all good thanks to super
}
}

// using non ES-6
function Foo () {
privateData.set(this, {...});
}

Foo.prototype.getPrivate = function() {
return privateData.get(this);
});

function Bar() {
Foo.call(this); // fine here
}

Bar.prototype = Foo.prototype;

The only limitation is that anything you want to be able to access the private data has to be defined inside the IIFE, you can't come along later and add a method to Foo's prototype. Although, if you're that concerened with performance, you shouldn't be altering prototypes willy-nilly anyway.

how to access javascript object variables in prototype function

Unfortunately you can't access a private variable. So either you change it to a public property or you add getter/setter methods.

function person() {

//private Variable
var fName = null;
var lName = null;

// assign value to private variable
fName = "Dave";
lName = "Smith";

this.setFName = function(value){ fName = value; };
this.getFName = function(){ return fName; }
};

see javascript - accessing private member variables from prototype-defined functions


But actually this looks like what you are looking for:
Javascript private member on prototype

from that SO post:

As JavaScript is lexically scoped, you can simulate this on a per-object level by using the constructor function as a closure over your 'private members' and defining your methods in the constructor, but this won't work for methods defined in the constructor's prototype property.

in your case:

var Person = (function() {
var store = {}, guid = 0;

function Person () {
this.__guid = ++guid;
store[guid] = {
fName: "Dave",
lName: "Smith"
};
}

Person.prototype.fullName = function() {
var privates = store[this.__guid];
return privates.fName + " " + privates.lName;
};

Person.prototype.destroy = function() {
delete store[this.__guid];
};

return Person;
})();

var myPerson = new Person();

alert(myPerson.fullName());

// in the end, destroy the instance to avoid a memory leak
myPerson.destroy();

Check out the live demo at http://jsfiddle.net/roberkules/xurHU/

How to create private variable accessible to Prototype function?

Yes. You can do this:

(function() {
var private = "hi";

Tree.prototype.genus = function(){
return ((typeof this.name !== 'undefined') ? this.name : 'Hybridicus Maximus');
};
Tree.prototype.bulk = function(){
return ((typeof this.size !== 'undefined') ? this.size : '8') + ' ft';
};
})();

Now, that'll provide a private variable that those functions can see, but it'll be a private "class" variable - all instances will share the same variable, in other words. If you want a private variable per instance, you have to do that in the constructor (or "init" method, or whatever), meaning the methods that share those privates would also have to be created there. (You could of course put a function on the prototype that would create the instance methods at construction time.)

edit — One thing you could do is use a technique like this to build a mechanism like jQuery's ".data()", so that you'd have a class variable that acts as a place to keep per-instance values. It'd be kind-of clunky, but it'd be workable.

Accessing private member variables of a class from a static method

static myClassPtr create(unsigned int val) {

create() is a static method of myClass, it is a member of this class. As such it it entitled to access all private members and methods of its class. This right extends not only to its own class instance, but any instance of this class.

As per my understanding private members should not be accessible.

... except by members of their class.

Let's create a completely pointless copy constructor for your class, the same copy constructor you would get by default:

myClass(const myClass &o) : m_val{o.m_val} {}

This copy constructor has no issues, whatsoever, of accessing m_val of the passed-in object. Exactly the same thing happens here. m_val is a private member of its class. It doesn't mean that only an instance of the same exact object can access its private members, it means that any instance of the class, or a static class method, can access the private class members.



Related Topics



Leave a reply



Submit