Reputation: 1588
Can someone explain why this occurs in Javascript?
var singleton = window.singleton || {};
singleton.methods = (function () {
var _private = function() {
console.log('outer private function');
}
return {
_private: function() {
console.log('inner private');
},
public: function() {
_private();
}
}
})();
singleton.methods.public();
My intuition leads me to believe that calling .public()
should log 'inner private'. It doesn't. If I change the public()
definition to this._private()
I get what I would expect. Why?
Upvotes: 1
Views: 80
Reputation: 1547
What you have is a closure. When you return a function in a closure, that function(s) becomes exposed, hence "public". Every function inside the closure preserve its true private scope. So when you call _private(); from public function, you are actually calling the inner function. Your public _private() belongs to the constructor, to call that you should apply a proper chain to it. Like so:
this._private()
Upvotes: 0
Reputation: 700870
The function that logs inner private
is a property in an object. The property can't be reached by only using its name, you have to specify that it's in the object.
In object oriented languages like C# and Java the scope of a method contains the identifiers from the object, but it doesn't work like that in Javascript. It only has function scope (and global scope), so you can't access object members without specifying which object they belong to.
Upvotes: 0
Reputation: 382474
You have a scope problem : _private
in your public
function refers to the one defined in the constructing closure (a closure is defined by a function call, the block you return doesn't define a scope).
If you want to log the _private
method of the object you return, change the definition to
return {
_private: function() {
console.log('inner private');
},
public: function() {
this._private();
}
}
Here's what the MDN says about closures :
In short, variables from the parent function of the closure remain bound from the parent's scope.
To resolve _private
in the public
function, you have to search in order
public
function itselfmethods
object. The function is found thereUpvotes: 2
Reputation: 3839
My guess is that you're coming from a language like Java where this.
is implied inside a method of an object when referring to an unqualified member name. In JavaScript, it's not, and that's the root of your problem.
The only exception in JavaScript is that the top-level scope -- window
in the browser -- is treated specially. If I declare var foo = "bar"
at the top level, it creates a property of window
called foo
with the value "bar"
and hence will appear to behave the way you're expecting:
this.foo = "bar";
alert(foo); // shows bar
alert(this.foo); // also shows "bar"
But in general, outside the top-level scope, this is not true. So your function named public
is looking for a scope variable called _private, and the property of the same object called _private
-- this._private
-- is not a scope variable in that or any other scope.
Upvotes: 0