javascript private member not accessible through public method - javascript

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.

Related

Javascript class variables - this. or var

Should 'this.' or 'var' be used to create variables in a Javascript class or does it not matter which is used. Obviously those defined with this. will be accessible from outside the object whereas those defined with var will not but are there any other differences?
function myClass() {
this.count = 0;
this.oTimer = null;
this.getCount = function() { return(this.count); }
}
oMyObj = new myClass();
oMyObj.getCount(); // returns 0
as opposed to
function myClass2() {
var count = 0;
var oTimer = null;
this.getCount = function() { return(count); }
}
oMyObj = new myClass2();
oMyObj.getCount(); // returns 0
Trying to explain a little bit more in detail than Dominique in the comments:
if you use the var keyword, the variable is only valid in the scope they are run. This means that after the constructor is run (the function body), the variables get lost (as they were only valid inside the constructor).
If you want to access the variables outside of the constructor (e.g. member-methods), you have to bind the variables to the class itself via the this keyword. Now their scope is the class itself, not just the constructor.
Edit:
Explaining further: while you can use the variables declared with var inside of methods that you also declared inside the constructor because they are defined in the same scope (see example of Question), it is not possible to access them through any other added methods that you add via Function.prototype.
To show this, I have created a little JSFiddle example
So it is generally better practice to define all variables of a class (that you don't only intent to use as temporary variables inside the constructor) with the this keyword.

Is it better practice to pass a variable to a prototype or reference a property inside the function?

I understand that functions should be self-contained on account of readability and code-recycling.
However, does this rule still hold true for functions which are in fact a part of an object prototype?
Should I prefer to pass in a variable to a prototype method when I can just directly access that value as a property from inside the object using this?
It is perfectly acceptable and common practice to access instance attributes from methods defined higher up the prototype chain, e.g.:
var Person = function(name) {
this.name = name;
};
Person.prototype.getName = function() {
return this.name;
}
var alex = new Person('Alex');
console.log(alex.getName());
In this example, calling getName() without the right context would not work as expected.
Also refer to the MDN page on Object.prototype, where this pattern is used a lot in their examples.

Why do I have to use "this" to access in inner property of a function

What is the difference between
function person(first_name, last_name) {
this.first = first_name
this.last = last_name
}
and this:
function person(first_name, last_name) {
var first = first_name
var last = last_name
}
Why only the first one makes person.first & person.last accessible outside the function?
The this keyword within a function is called the invocation context.
1) If you define your function as a member of an object (a method):
myObject.someMethod = function() { this.x = 2; };
then the invocation context, this, is the object to which the method is being added, myObject. So after calling myObject.someMethod(); above, myObject.x is then 2. The member x is undefined until you call the method, unless you defined it before.
2) If you use your function as a constructor with the new keyword, then this refers to the new object that is being created:
function MyX() { this.x = 3; };
var myX = new MyX();
You'll then have property myX.x set to 3.
Note that I called my constructor MyX(), not myX(). You should call yours Person(), not person(). It's just a convention, but it is useful to indicate that a function is meant to be used as a constructor.
3) Finally, if you use this within a function that you call as neither a method nor a constructor, then this refers to the global object (document or, equivalently, window). Note however that if you are using javascript in strict mode (which you should do), this is undefined in such a situation, which means that you basically cannot use this in a function that is not a method or a constructor.
Your specific question refers to case 2), the constructor. this.x = 3 in the constructor just sets property x of the newly created object. After some object myX is created, you can then access and modify x externally as any other object property using myX.x.
when you write constructor function ( using new) - you add properties using this.XXX
then you do :
var p = new Person('s','d');
and then you have access to p.first etc.
in the second example :
youre not creating any properties..
youre only creating private variables.
so you cant access them...
By using this.something you're saying that THIS is an object and something is his property.
By using var, you're saying that it's just a variable and not a property.
More information about variable vs property:
http://javascriptweblog.wordpress.com/2010/08/09/variables-vs-properties-in-javascript/
Because of function scope.
A variable lifetime is between the curly braces of the function. The this keyword allows to access the function properties outside of it.
Definitely take a look at this link: https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope
'var' keyword make a variable scoped. In the last example var first and var last create variable accessible only in the scope of the function. You can see this as a local variable in a constructor.
when in javascript you declare a variable as
var variable
it only exists inside the method where you declared it. If you want a variable to be accessible for everyone (that is, global) it has to be declared without the 'var' part
You do not necessarily have to use this. It'd also work fine if you've got a structure like this:
Person = function(first_name, last_name) {
var first, last;
create(first_name, last_name);
function create(first_name, last_name) {
first = first_name
last = last_name
}
return {
firstName: first,
lastName: last
}
}

How to override private variable in 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.

JavaScript Classes and Variable Scope

I'm relatively new to JS and I'm having issues properly emulating OOP principles.
I guess I have two questions. Question the first is regarding the many ways to declare variables.
Say I have a class:
function clazz(a)
{
this.b = 2;
var c = 3;
this.prototype.d = 4; // or clazz.prototype.d = 4?
}
var myClazz = new clazz(1);
Am I correct in the following assessments:
a is a private variable that is instance specific (i.e. different instances of clazz will have unique and independent variables 'a'). It can be accessed from within clazz as: 'a'.
b is a public variable that is instance specific. It can be accessed from within clazz as 'this.b' and from outside clazz as 'myClazz.b'.
c is a private variable that is static, or class specific (i.e. different instances of clazz will share the same 'c' variable). It can be accessed from within any instance of clazz as 'c' and changes in instance of clazz are reflected in all instances of clazz.
d is a public variable that is static/class specific. It can be accessed from anywhere via 'clazz.prototype.d' or 'myClazz.prototype.d'.
The overall issue I have with my understanding of the variable scheme is that there's no way to declare a private variable that is NOT static (i.e. a unique version for every instance of the class).
The second question is with respect to different types of class declarations.
I've been using:
var MySingleton = new function() {...};
to create singletons. Is this correct? I'm also unsure as to the effect of the "new" keyword in this situation as well as appending () function braces to the end of the declaration as so:
var MySingleton = new function() {...}();
I've been using this pattern to declare a class and then instantiate instances of that class:
function myClass() {...};
var classA = new myClass();
var classB = new myClass();
Is this the proper method?
You are right for a and b:
a is an argument, available only within the scope of the constructor function.
bis a public instance variable, available on all instances created with that constructor function.
c is a private variable, accessible only within the constructor function.
The d declaration is invalid, because the prototype object is meant to be used only on constructor functions, like Clazz.prototype.d = 3;, if you do it like this, the variable will be shared, but you can assign a value on an specific instance, and the default value will be shadowed (through the prototype chain).
For "private variables" you can use the way you declare c, for example:
function Clazz(){
var c = 3; // private variable
this.privilegedMethod = function () {
alert(c);
};
}
Privileged methods, are public, but they can access "private" variables declared inside the constructor function.
For creating singletons, the easiest way is maybe to use an object literal, like:
var myInstance = {
method1: function () {
// ...
},
method2: function () {
// ...
}
};
And if you want private members on your singleton instance, you can:
var myInstance = (function() {
var privateVar = '';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// all private members are accesible here
},
publicMethod2: function () {
}
};
})();
This is has been called the module pattern, it basically allows you to encapsulate private members on an object, by taking advantage of the use of closures.
More info:
Private Members in JavaScript
Introduction to Object Oriented JavaScript
Edit: About the syntax you post:
var mySingleton = new (function() {
// ...
})();
By using the new operator, you are declaring and using in one step an "anonymous constructor function", which will generate a new object instance, it is valid but I personally would prefer the "module" pattern approach, to create my own object instance (and avoid new).
Also, reading new function () {}, I think that is not really intuitive and may create confusion, if you don't understand well how the new operator works.
About the parentheses, they are optional, the new operator will call the function constructor without parameters if you don't add them (see ECMA-262, 11.2.2).
OK, lets go over this:
'a' is an argument passed to the constructor of your class. It will only exist for the duration of the constructor's invocation. This means you should probably store its value somewhere.
'b' is a public instance member. It is instance specific (altho, since you're assigning the value in the constructor, all instances will initially have the same value for 'b').
'c' is a private instance member. It will, however, only be accessible inside your constructor since it is only defined in that scope. Unless you refer to it from a closure inside your constructor function, its fate will be similar to that of 'a' above.
'd' is a public instance member. Each instance of your class will have a member 'd' with the value 4 initially. Note however that assigning a reference type object to a prototype member of your class (such as 'd') will make every instance member 'd' refer to the same object. Example:
MyClass.prototype.d = { prop1: 'val1', prop2: 'val2' };
var a = new MyClass();
var b = new MyClass();
a.d.prop1 = 'foo'; // is the same as: b.d.prop1 = 'foo';
Static members of the class are defined using:
function MyClass()
{
// ...
}
MyClass.staticMemeber = 'I am a static member';
You should probably not treat MyClass.prototype as a place to hold your static members/methods.Everything assigned to a classes' prototype is in turn a member of each of its instances.
When ()'s are attached to a function definition (right after the block), the function is executed. That means:
var myFunc = function() { alert('blah'); }();
would result in nothing more than a method invocation. The following code:
var MySingleton = new function() {...}();
would mean 'use the return value from function() as the constructor for MySingleton'.

Categories

Resources