I am reading a tutorial on public/private methods and can\'t make sense of the difference.
For a private method it says, \"Private members are made by the constructor. O
Opening a new function body creates a new scope. This kind of scope is called a closure in JS. Variables created within that scope are accessible in all its sub-scopes. This means any var
-created variable will be made visible to sub-functions. In this example, myTemporaryVar is accessible within subScope.
function myParentScope() {
var myTemporaryVar = "sample";
function subScope() {
console.log(myTemporaryVar);
}
return subScope();
}
When you use a function with the new
keyword, a new closure is created for the current instance. Any function created within that constructor will keep access to the scope variables. In the next example, the function sayHi can access the temporary variable myName.
function Person(name) {
var myName = name;
this.sayHi = function() {
console.log("Hi, my name is " + myName + ".");
};
}
p = new Person("Bob");
p.sayHi(); // Hi, my name is Bob.
Actually, passed parameters are the same as var
-created variables. The constructor's parameters are accessible within any sub-function. So the previous example can be reduced to:
function Person(name) {
this.sayHi = function() {
console.log("Hi, my name is " + name + ".");
};
}
p = new Person("Bob");
p.sayHi(); // Hi, my name is Bob.
This is a very unique feature of JavaScript because it means var
-created variables still exist after the end of the function as long as there still is a way to access them.
Closures can be "abused" to create private members with getter and setter functions.
function Person(name) {
this.getName = function() {
return name;
};
this.setName = function(newname) {
name = newname;
};
}
p = new Person("Bob");
console.log(p.getName()); // "Bob"
p.setName("Alice");
console.log(p.getName()); // "Alice"
p.name; // undefined
The getter and setter have to be created within the constructor in order to access the var
-variable. Methods added in the common prototype-extension way can't access them. Prototype-methods have to use the setters and getters too, which makes the privacy of such variables quite useless.
Person.prototype.sayGoodMorning = function() {
console.log("Good morning, my name is " + this.getName() + ".");
}
The only way to directly access the variable within a method is to actually create it in the constructor. But putting all methods inside the constructor is extremely inefficient as a new copy of the methods will be created for each instance. This is why many people prefer simply using custom notation to identify would-be private members. The Google JavaScript Style Guide recommends placing an underscore at the end of the variable name.
function Person(name) {
this.name_ = name;
}
Person.prototype.getName = function() {
return this.name_;
}
Person.prototype.setName = function(name) {
this.name_ = name;
}
Person.prototype.sayGoodMorning = function() {
console.log("Good morning, my name is " + this.name_ + ".");
}
It is the responsibility of the programmer to not be stupid and access the would-be private members. Note that this goes in total contradiction with Crockford's opinion, but to each is own. I learned JS after Python, so the underscore privacy is like a second nature to me.