Reputation: 27203
Please consider the following code:
function Outer(){
function Inner(){
var private="something";
this.method = function(){
//some code here
};
}
var inner = new Inner(); //Why does this line not throw an error?
alert(inner.private); // not accessible here
inner.method();//no errors here
}
I am unable to understand why method() call doesn't throw an error and the variable reference throws an error? I understand that variables have their scope only within the function in which they are declared? But what about the scope of functions ?
Upvotes: 1
Views: 74
Reputation: 39280
The line var inner = new Inner() does throw an error as inner is not defined, it's only accessible within the body of the Outer function.
The inner.private is not accessible as a property of inner because it's a closure variable. So (new Inner()).private does not exist. (private seems to be a keyword in JS so I changed it to priv in sample code)
It is accessible within the Inner function body because code within the function body keeps a reference to closure variables.
function Inner(){
var priv="something";
this.method = function(){//wrong, should declare as prototype
console.log("private from within Inner function body:"
,priv)
};
}
var inner = new Inner();
console.log(inner.priv); //=undefined
inner.method();//=something
A function property of an object that will have many instances; like Inner can have many instances like: var a=new Inner(); var b = new Inner()... Should not be defined with this. You should use prototype instead.
When you use prototype you can't use private variables in the prototype functions because private (closure) variables are only accessible within the main function body. This is why many developers use _private
or private_
to indicate it's private since JavaScript does not have a good way to make members private without messing up the prototype.
function Inner(){
var priv="private";//wrong
this._priv="private"
}
Inner.prototype.method=function(){
//cannot access priv
console.log(this._priv);//no problem
}
There is maybe one case where you can use privates in this way and that is when there is only one instance of your object.
var Mediator=(function(){
var events={};//private, other code can't mess this up
return{
addEvent:function(eventName){
events[eventName]=(events[eventName])?
events[eventName]:[];
},
addLisener:function(eventName,func){
events[eventName].push(func);
return events[eventName].length-1;
}
//more stuff like removeListener, trigger ...
}
})()
You can read about prototype in this basic example. You can run the code in Chrome or Firefox with firebug console. Press F12 to open it and paste the code from that link in the console. Then fiddle with it as you like and see if you get the expected output and understand prototyping in JS.
Upvotes: 1
Reputation: 816600
There is nothing complicated about it and it has nothing to do with data types.
new Inner()
creates a new object. You are assigning a property to that object in the constructor
this.method = function(){...};
On the other side, there is not such property private
. You never do this.private = ...;
. private
is just a variable local to the Inner
function.
Here is another example which is equivalent to your code but hopefully makes it clearer:
function createObject() {
var someVariable = '42';
var obj = {};
obj.foo = 'bar';
return obj;
}
var myObject = createObject();
// works, since we assigned the property to the object
console.log(myObject.foo);
// does not work, we never assigned such a property to the object
console.log(myObject.someVariable);
Inside createObject
two variables are declared, someVariable
and obj
. obj
is an object, we assign a property to it and return it from the function. someVariable
has nothing to do with the object, but could be used for other purposes within the function.
Upvotes: 3