How to override private variable in javascript? - javascript

// base function
function Man(name) {
// private property
var lover = "simron";
// public property
this.wife = "rocy";
// privileged method
this.getLover = function(){return lover};
// public method
Man.prototype.getWife = function(){return this.wife;};
}
// child function
function Indian(){
var lover = "jothika";
this.wife = "kamala";
}
Indian.prototype = aMan;
var aMan = new Man("raja");
oneIndian = new Indian();
oneIndian.getLover();
I got answer as "simron" but I expect "jothika".
How my understanding is wrong?
Thanks for any help.

First of all your code doesn't work at all and it's wrong.
Here's the code that works:
// base function
function Man(name) {
// private property
var lover = "simron";
// public property
this.wife = "rocy";
// privileged method
this.getLover = function(){return lover};
// public method
Man.prototype.getWife = function(){return this.wife;};
}
// child function
function Indian(){
var lover = "jothika";
this.wife = "kamala";
this.getLover = function(){return lover};
}
Indian.prototype = new Man();
Indian.prototype.constructor = Indian;
var oneIndian = new Indian();
document.write(oneIndian.getLover());
aMan didn't exist until you declared it.
Also you should have set the ctor to Indian.
And at last, getLover is a closure that refers to Man and not to Indian.
Declaring it again refers it to the right scope.
See here and here for further details and improvements of your code.

The getLover property on the instance refers to the closure you defined within the Man constructor. The lover local variable inside Man is the one in-scope for that function. The lover variable you declared inside Indian has nothing whatsoever to do with the one declared inside Man, no more than local variables declared inside other functions do.
For Indian to manipulate the private lover variable inside Man, you would have to give Indian some access to it via an accessor function -- but then everything would be able to change it via that same accessor function.

My advice: get rid of this whole priviledged method crap and don't try to shoehorn concepts from one language into another.
For performance reasons, methods should reside in the prototype. Otherwise, a new function object (which forms a closure over the constructor's local vaiables) has to be created for each instance, which is highly inefficient.
If you want to hide properties (ie 'private' fields), add a prefix like _private_ to their name and tell the programmer not to do stupid things.

Related

Encapsulation / Data Hiding in Javascript?

I would like to understand the concept of Encapsulation in JavaScript, and how to make my properties and methods public or private.
I'm playing around with this example:
var person = function(newName, newAge) {
// Private variables / properties
var name = newName;
var age = newAge;
// Public methods
this.getName = function() {
return name;
}
// Private methods
var getAge = function() {
return age;
}
// Public method, has acces to private methods
this.giveAge = function() {
return getAge();
}
}
var jack = new person("Jack", 30);
console.log(jack.name); // undefined
console.log(jack.getName); // Jack
console.log(jack.getAge()); // TypeError: jack.getAge is not a function
console.log(jack.getAge); // undefined
console.log(jack.giveAge()); // 30
So, variables var name and var age are private. To access them I use public methods by using .this reference. So anything that is var inside my function is private, and anything that's .this inside my object is visible outside.
I guess that's cause person is visible, so it exposes all of its properties.
Am I on the right track? Is this the right way to hide or expose your properties / methods?
And one more question, why does console.log(jack.getAge()); throws an error? And when referencing functions I "stored" in variables, should I put () at the end of that function, it works both ways, so I don't know what do use?
Thanks!
I guess that's cause person is visible, so it exposes all of its properties.
Correct.
Am I on the right track? Is this the right way to hide or expose your properties / methods?
If you want to do it, then yes, this is a fairly standard way to do it. There's at least one other way as of ES2015, but with (probably) more overhead.
And one more question, why does console.log(jack.getAge()); throws an error?
Because the jack object doesn't have a getAge property, so jack.getAge yields undefined, which isn't a function. There's a getAge variable inside the context that the giveAge closure has access to (along with age and name), but jack doesn't have a getAge property.
And when referencing functions I "stored" in variables, should I put () at the end of that function, it works both ways, so I don't know what do use?
No, it doesn't work both ways. jack.getName gets a reference to the function. jack.getName() calls the function and gets its return value.
I should note that there's no point to the getAge function. It's only accessible to closures defined within the person function, just like age and name are. So anything that would use getAge would just use age instead and avoid the function call.
Just for completeness, I'll note that many people don't worry about truly private properties in JavaScript, opting instead for "private by convention" — e.g., they use a naming convention (such names starting with _) to mean "don't touch these, they're private." That doesn't do anything to prevent people using them, of course, it just indicates that they shouldn't. Folks advocating this usually point out that in many languages with "true" private properties/fields (Java, C#), those properties/fields are accessible with only a small amount of effort via reflection. And so, the argument goes, just using a naming convention is "as private."
I'm not agreeing (nor particularly disagreeing) with that, it does require rather more work in Java or C# to access private properties than public ones. I'm just noting that the "private by convention" approach is quite common, and frequently "good enough."
I guess that's cause person is visible, so it exposes all of its properties.
not exactly. First of all, person is a regular function. it can perfectrly be called without the new-keyword, but the results will blow up your whole application.
To understand why, you should first understand what the new-keyword does behind the scenes. This would be an js-implementation:
function fakeNew(constructor, ...args){
if(typeof constructor !== "function"){
throw new TypeError(constructor + " is not a constructor");
}
//create a new Instance of the constructors prototype-property
var instance = Object.create(constructor.prototype);
//invoke the constructor with the scope set to the instance and the provided arguments
var result = constructor.apply(instance, args);
//check wether the returned value is an Object (and functions are considered as Objects)
if(result === Object(result)){
//then return the result-value in favor to the instance
return result;
}
//otherwise return the instance
return instance;
}
On the other hand, any function can also be a constructor; no special needs, it's all up to you.
So back to jack
var jack = person("Jack", 30); //would result in the following desaster:
console.log(jack); //undefined, since person doesn't return anthing
console.log(jack.getName());
//will throw, since jack is still undefined, and therefore doesn't have any properties
//BUT:
console.log(window.getName()) //will return "Jack" now
console.log(window.getAge); //undefined, but this is fine
//global scope has not been polluted with this one, cause getAge was a local variable inside the function-call
console.log(window.giveAge()) //can still call the enclosed (private) function getAge()
then
var jill = person("Jill", 28);
//will overwrite the global functions and expose new values now
console.log(window.getName(), window.giveAge()) //"Jill", 28
//and Jack is kind of gone, well the variable is left but the variable contained undefined, so...
next thing is scoping. let's assume you made this correct
//first let's add a function that executes on the scope
//inside the constructor
this.getNameAndAge = function(){
return this.getName() + ": " + getAge();
}
.
var andy = new person("Andy", 45);
var joe = new person("Joe", 32);
//let's make Andy a little younger
andy.getNameAndAge = joe.getNameAndAge;
console.log(andy.getNameAndAge(), andy.getName() + ": " + andy.giveAge());
//will result in "Andy: 32", "Andy": 45
waaaaat?
well you've overridden the public method getNameAndAge.
the name is accessed by invoking the (also public) method getName() on the current Object.
but giveAge() still the enclosed variable from the scope where this specific "instance of the getNameAndAge-function" was declared, and therefore it's from Joe's function call.
To understand the impacts of this, let's make the scoping even more weird
funciton Animal(species, _name){
//species is likewise a local variable and can be enclosed, modified, or whatever
//we don't need to write it to some different variable
//but we want to expose the name of this animal, since it should be possible to change it later
//without the need to create a getter and a setter just to change the property of _name
this.name = _name;
this.whoAreYou = function(){
//so we concat the enclosed value from species with the name-argument on this object
//in the hope that everything will be alright.
return species + " " + this.name;
}
}
var jack = new Animal("dog", "Jack");
var jill = new Animal("cat", "Jill");
var joe = new Animal("fish", "Joe");
console.log(jack.whoAreYou()); //"dog Jack"
console.log(jill.whoAreYou()); //"cat Jill"
console.log(joe.whoAreYou()); //"fish Joe"
//as far so good; till now ...
//since these properties are still writable someone will start and move them around
//maybe like a callback
function someFunction(someArg, callback){
console.log(someArg, callback());
}
someFunction("Who are you?", jack.whoAreYou);
//or sth. like this:
//you may not believe that someone would ever do that, but it will happen!
jack.whoAreYou = jill.whoAreYou;
console.log(jack.whoAreYou());
//and now the poor dog has an Identity-crisis.
//the first one will result in:
"Who are you?", "dog undefined"
//the latter will log "cat Jack"
or even more fummy if sth. like this happens:
var fn = joe.whoAreYou;
console.log(fn.call(jack), fn.call(jill), fn.call(joe), fn.call(Animal));
//cause now they are all fishes, even the Animal-constuctor
I don't want to say that this is bad, or that you should avoid it but there is the way that it works, and that should be considered.
cause this way provides us with prototypal inheritance, and a great way to write mixins, without writing wrapper-methods all the time.
You can look at that as "i need to secure my private state", or "I work in whatever enviorment you provide to me"
And one more question, why does console.log(jack.getAge()); throws an error?
because jack.getAge is undefined and undefined is no function
var getAge = function() {
return age;
}
another comment to this line
in JS function- and variable-declarations are hoisted and therefore available from the beginning of the function. Expressions are not.
var person = function(){
//...
foo();
bar();
baz();
function foo(){ console.log("this will work"); }
var bar = function(){ console.log("this will fail"); }
//because to this point, bar was delared and assigned with undefined,
//and we remember? undefined can't be invoked
return whatever;
function baz(){ console.log("event this would work"); }
//unless some preprocessor decided (falsely), that this function can be removed
//since it is after the return-statement, and is therefore unreachable
}

Private JavaScript functions - this.name vs. var name

If I'm using some private functions in a class do certain naming conventions yield better performance or offer different functionality...or is it simply a matter of preference?
var MyClass = function() {
var private1 = function(msg){
// Do stuff.
console.log(msg);
};
this.private2 = function(msg) {
// Do stuff.
console.log(msg);
};
};
Your two variables have very different access so which one to use depends upon which type of access you want to offer, not just a coding style preference.
In your example, private1 is a local variable to your constructor and is ONLY available to code inside the constructor. It is NOT available to any code outside the constructor. It is actually private.
var yourObj = new MyClass();
yourObj.private1(); // undefined, will not work
private2 is an instance variable of a MyClass object you create with the new operator and is reachable by any code as yourObj.private2(). It is not private in any way - it is a publicly reachable method. Example:
var yourObj = new MyClass();
yourObj.private2(); // works
So private1 is private and private2 is public. One should select the implementation method that matches the desired goal of the code. This is not just a coding style preference.
private1 is a function inside constructor MyClass and private2 is function of MyClass instance:
var cl = new MyClass();
console.log(cl.private1); // undefined
console.log(cl.private2); // function

javascript private member not accessible through public method

I have following setup. method and method1 both are public methods of class Student. But why ca only "method" access private variable p
​function Student() {
var p = 10;
this.method = function() {
document.write(p);
};
};
Student.prototype.method1 = function() {
document.write('here');
document.write(p);
};
var s = new Student();
s.method();
s.method1();
​
How does it make sense, I mean is it "a public method that does not have access to private members!"
There is no magic going on with JavaScript's prototypal inheritance.
Student is still a function and p is local to that function. It cannot be accessed from outside code in any way. method can access p because it is defined inside Student and therefore forms a closure, but method1 is declared outside Student's scope.
Assigning a function to another function's prototype cannot give it access to its local variables.
Consider this example:
var p = 41;
function foo() {
console.log(p);
}
​function Student(){
var p = 10;
};
Student.prototype.bar = foo;
var s = new Student();
s.bar();
foo();
You might think that because foo is invoked as an object method it could have access to the local variables, but that's just not the case. The only value that is determined dynamically is this, it is a special keyword. All other variables are strictly defined through the scope chain.
method1 is defined outside of the base class definition for Student. As such, it cannot access variables declared as private inside the base class definition. If it could, then you could get around private variable restrictions in existing classes by just defining a public method for that class.
In JavaScript, public methods like method1 (i.e. methods added to the prototype) do not have access to private variables, but "privileged" methods like your method do.
Remember, JavaScript doesn't have the same scoping rules as other object-oriented languages. The method method forms a closure around the private variables within the Student constructor function, while method1 does not.

Declaring variables in JavaScript class: this vs. var. Difference?

What's the difference between declaring internal variables inside a JavaScript class with this vs var?
Example:
function Foo( ) {
var tool = 'hammer';
}
function Foo2( ) {
this.tool = 'hammer';
}
One difference we're aware of is Foo2.tool will yield "hammer" whereas Foo.tool will yield undefined.
Are there other differences? Recommendations for one vs. the other?
Thanks!
there is no "one or the other" here since the purpose of the two are different.
consider this:
var Melee = function(){
//private property
var tool = 'hammer';
//private method
var attack = function(){
alert('attack!');
};
//public property
this.weapon = 'sword';
//public methods
this.getTool = function(){
return tool; //can get private property tool
};
this.setTool = function(name){
tool = name; //can set private property tool
};
};
var handitem = new Melee();
var decoration = new Melee();
//public
handitem.weapon; //sword
handitem.getTool(); //hammer
handitem.setTool('screwdriver'); //set tool to screwdriver
handitem.getTool(); //is now screwdriver
//private. will yield undefined
handitem.tool;
handitem.attack();
//decoration is totally different from handitem
decoration.getTool(); //hammer
handitem.weapon in OOP is a "public property", accessible from the outside. if i created this instance of Melee, i can access and modify weapon since it's open to the public.
handitem.tool is a "private property". it's only accessible from inside the object. it is not visible, not accessible, and not modifiable (at least directly) from the outside. trying to access it will return undefined
handitem.getTool is a "public method". since it's on the inside of the object, it has access the private property tool and get it for you from the outside. sort of bridge to the private world.
handitem.attack is a private method. like all private stuff, it can only be accessed from the inside. in this example, there is no way to call attack() (so we are safe from attack :D )

Prototype vs. Not, what are benefits?

Here I made two objects; one has accessor methods created in the constructor, the other in the prototype. Why would one choose one of these over the other?
function spy1(name){
this.name = name;
var secret;
this.setSecret = function(message){
secret = message;
};
this.getSecret = function(){
return secret;
};
}
function spy2(name){
this.name = name;
this.secret;
/* (see comment) was:
var secret;
*/
}
spy2.prototype.setSecret = function(message){
this.secret = message;
/*was:
secret = message;
*/
};
spy2.prototype.getSecret = function(){
return this.secret;
/*was:
return secret;
*/
};
bond = new spy1("007");
smart = new spy2("86");
bond.setSecret("CONTROL is a joke.");
smart.setSecret("The British Secret Service is for sissies.");
The primordial differrence is that in your first example, without prototype, the getSecret and setSecret function implementation will reside on every instance of spy1.
On your second example, the functions are defined on the prototype, and all instances refer to them directly, you can test it:
var bond = new spy1("007"),
bond2 = new spy1("007");
bond.getSecret === bond2.getSecret; // <-- false since they are two functions
var smart = new spy2("86"),
smart2 = new spy2("86");
smart.getSecret === smart2.getSecret; // <-- true since is the same function
// on all instances
Also note what #T.J. commented, in your second example, using the prototype, you don't have access to the constructor function closure, and for that you are making a window.secret global variable.
If you intend to work with privileged methods, extending the prototype is not an option, all the methods that need access to the variables defined within the scope of the constructor function need to be declared inside of it...
See also: Closures.
In your first example, you're creating new functions for each instance of the object whenever you instantiate a new one. In the second, only a single copy of the function is created which is used by all the instances.
The second way can save memory. You can also use prototype chaining to implement inheritance.
Btw, your second example won't work as written. the secret variable in spy2 is local to the constructor. In the setSecret and getSecret functions in the prototype, you're accessing a single global variable.
With the second version you end up with a cleaner "constructor".

Categories

Resources