Reputation: 1869
Consider this code,
var getPerson = function() {
var _name = "";
var person = {};
person.getName = function() {
return _name;
}
person.setName = function(value) {
_name = value;
}
return person;
}
p1 = getPerson();
p1.setName("foo");
p2 = getPerson();
p2.setName("bar");
console.log(p1.getName()); // logs "foo"
console.log(p2.getName()); // logs "bar"
Could someone explain the scope of _name here? p1._name and p2._name do not exist. Where is that variable really being stored?
Upvotes: 0
Views: 674
Reputation: 1666
I think you are probably coming to JavaScript from a Java background.
var _name = "";
defines the _name
variable in the scope of the anonymous function (the function assigned to getPerson
). The variable is not attached to any object, it's just an ordinary variable.
If you really want to do p1._name and p2._name, you can do one or two workarounds.
var getPerson = function() {
var person = {
_name: ''
};
person.getName = function() {
return this._name;
}
person.setName = function(value) {
this._name = value;
}
return person;
}
p1 = getPerson();
p1.setName("foo");
p2 = getPerson();
p2.setName("bar");
console.log(p1.getName()); // logs "foo"
console.log(p2.getName()); // logs "bar"
console.log(p1._name); // logs "foo"
console.log(p2._name); // logs "bar"
var getPerson = function() {
var _name = "";
var person = {
get _name () {
return _name;
}
};
person.getName = function() {
return _name;
}
person.setName = function(value) {
_name = value;
}
return person;
}
p1 = getPerson();
p1.setName("foo");
p2 = getPerson();
p2.setName("bar");
console.log(p1.getName()); // logs "foo"
console.log(p2.getName()); // logs "bar"
console.log(p1._name); // logs "foo"
console.log(p2._name); // logs "bar"
There are many other ways you can accomplish this; JavaScript is a dynamic language.
What you have above is called a closure. By returning person
, you expose the methods person.getName
and person.setName
. Because these methods are defined inside getPerson
, they get access to the _name
variable too (because _name
is defined inside the same function).
Codes outside getPerson
can't access _name
, but they can access if (in a controlled manner) through the getName and setName methods. This creates privacy for the _name
variable.
Upvotes: 1
Reputation: 707396
_name
is scoped to any code within the getPerson()
function.
In Javascript, a local variable in a function is scoped to within that particular invocation of the function and each invocation of the function creates a new set of local variables. Also, those local variables are garbage collected just like other variables. They are not strictly stored on a stack that is destroyed when the function exits.
Because of the garbage collection, a variable inside a function will survive as long as code that is still reachable has a reference to that variable. So, in your getPerson()
function, the scope of the _name
variable is a particular invocation of the getPerson()
function, but the lifetime of the variable is as long as some code can still reach that variable, even long after the invocation of getPerson()
has finished.
This is referred to as a closure in Javascript and is an extremely valuable and useful tool.
Because person.getName()
and person.setName()
still have a reference to the _name
variable even long after the getPerson()
function has finished execution, it will remain alive and will not be garbage collected by the language.
So, the scope
is determined by the declaration of the variable. _name
is scoped to within the function that is it declared in and any other child scopes that also exist within that function. Javascript has lexical
scope (which means the scope is determined by where/how it is declared). But, the lifetime of a variable within a scope is separately determined by the garbage collector and a variable within a scope can live much beyond the execution of the function that created the scope as long as some other reachable code still has a reference to that variable.
I like to think of a function scope as, itself, a garbage collected entity in Javascript. While some implementations of Javascript might even be more granular than a whole scope (e.g. garbage collecting individual variables within the scope as possible), the concept of a scope that is garbage collected instead of stack-based gives you a framework for understanding the difference between a language like Javascript and a language like C++ that uses an explicit stack frame to determine the life of a local variable.
Upvotes: 1
Reputation: 25393
_name
is scoped to the getPerson
function, since it is there that it is declared using the var
keyword.
Any functions that are nested inside getPerson
will inherit the variables declared in getPerson
, and they can override this to declare their own variables. This concept is called closure
and is worth understanding before doing any serious development in JavaScript.
In JavaScript, scope is not determined by block (as in Java), but is function scoped.
So, the _name
in the setName
function is the same _name
that is declared in getPerson
.
Upvotes: 1