Remember this: In JavaScript, only function creates scope but the visibility and the life cycle of the variables are not limited to the function definition.
A local variables is created with keyword “var” and it lives within the function scope. They are private variables because they can not be accessed directly outside the function the scope but can be accessed by privileged methods – inner functions of the object.
Variables which are referred by keyword “this” are considered as public variables because they can be accessed through the object. The keyword “this” is not optional because JavaScript will only evaluate it as a local variable name without “this”. Global variables are those defined outside any function and they should be avoided.
The other fundamental concept which needs to be emphasized is that JavaScript is prototype-based inheritance and not class-based. The object definition is defined with prototype and it can be changed anytime as it needs. An instance is usually created with keyword “new” and it gets a reference to the prototype, which means it will get the updated prototype even if the change is made to the prototype chain after the creation of the instance. While prototype can manipulate all the properties associated with the object, private variables are not visible to the prototype methods.
Below is a simple example to illustrate the scope of different variables as well as the prototype concept.
function Cat(name, age) {
this.age = age;
// add a privileged method
this.description = function() {
this.id ? this.id++ : this.id=1;
console.log("name = " + name,", age = "+this.age, ", version = ", this.id);
}
}
var myCat = new Cat("Kitty", 3);
myCat.description(); // name = "Kitty", age = 3, version = 1
// add a new method
Cat.prototype.setAge = function(newAge) {
this.age = newAge;
};
myCat.setAge(4);
myCat.description(); // name = "Kitty", age = 4, version = 2
var myOtherCat = new Cat("Lily", 5);
myOtherCat.description(); // name = "Lily", age = 5, version = 1
You can also create the Cat object with “var Cat = { name: “Kitty”, age: … };”. As you see, you can not pass in the parameters in this case and all the properties within are public variables.
The other factor affects the JavaScript scope is the closure. JavaScript closure is the inner function can access the parameters and variables after the outer function is returned. Closure is basically a way to manipulate local variables with the return of an inner function which accesses local variables. Below is an example:
function Cat() {
var name = "Kitty";
var age = "1";
this.version = 1;
var setAge = function(newAge){
age = newAge;
console.log(age);
//this.version is undefined here
};
return setAge;
}
var myCat = new Cat(); // myCat is the function setAge
console.log(myCat(2)); // 2
console.log(myCat(3)); // 3