Object Composition
Another way to create Objects in JavaScript is to use the Prototype chain.
When using the prototype chain you start with a base function, which you then attach behaviour to using the prototype
operator. When methods are called on a function the methods are looked up in the prototype chain.
Starting with a Light
function
var Light = function(color){
this.color = color;
this.state = "off";
};
You add methods to it’s prototype chain like this:
Light.prototype.on = function(){
this.state = 'on';
}
Light.prototype.off = function(){
this.state = 'off';
}
Light.prototype.status = function(){
return "This is a " + this.color + " light and it is currently " + this.state;
}
You can use the Light
function like this:
var light = new Light("green");
light.on();
//the state variable is NOT private
console.log(light.state);
//this is a member function
console.log(light.status());
Note that the state
variable is publicly accessible.
No private variables
A downside of using the Prototype chain is that one can’t create private variables. The only way to create private variables is to use a factory function in conjunction with a closure.
A closure is an inner function that have access to the scope of it containing function. This is a very useful concept in JavaScript to create private variables and methods.
You can learn more about closures here
You can create a Prototype chain with a private state
variable like this.
function TheLight(color){
//this is accessed as a closure
var state = "off";
var Light = function(color){
this.color = color;
};
Light.prototype.on = function(){
//this is no longer a Light instance variable
state = 'on';
}
Light.prototype.off = function(){
//this is no longer a Light instance variable
state = 'off';
}
Light.prototype.status = function(){
return "This is a " + this.color + " light and it is currently " + state;
}
return new Light(color);
}
You can now use TheLight
like the example below. Note that the state
variable is now private.
var light = TheLight("red");
console.log(light.status());
light.on();
console.log(light.status());
// state is not accessible now
console.log(light.state);
Note: ES6 classes can’t have private variables as they are just a sugar coated Prototype chain. Go figure!
ES6 Classes
In ES6 you can now creates a class like this:
class Light {
constructor(color){
this.color = color;
this.state = "off";
}
on(){
//this is no longer a Light instance variable
this.state = 'on';
}
off(){
//this is no longer a Light instance variable
this.state = 'off';
}
status(){
return "This is a " + this.color + " light and it is currently " + this.state;
}
};
This works exactly the same as a Prototype chain and can be used like this:
var light = new Light("green");
light.on();
//the state variable is NOT private
console.log(light.state);
//this is a member function
console.log(light.status());
Why bother?!
You might wonder why would one use the Prototype chain in JavaScript. It is useful for Inheritance in JavaScript, inheritance is when Objects can get behaviour from other objects without implementing it themselves. Hold onto that thought for later.