JavaScript does not have classes like others have said. Inheritance is resolved through prototyping which in essence does nothing more then create non-deletable property references on a newly created object. JavaScript also has alternatives for simple data objects, namely object literals.
The variation of a 'Class' in JavaScript should be defined as such:
// I use function statements over variable declaration
// when a constructor is involved.
function Person(name) {
this.name = name;
}
// All instances of Person create reference methods to it's prototype.
// These references are not deletable (but they can be overwritten).
Person.prototype = {
speak: function(){
alert(this.name + ' says: "Hello world!"');
}
};
var Mary = new Person('Mary');
Mary.speak(); // alerts 'Mary says: "Hello world!"'
The this
reference always points to the owner of the function
. If you call Person
without the new
operator, the owner will be the global scope (window). If you do not use the this reference to assign properties to your instance, then the properties will simply be declared as variables. If you do not use the var
statement, then those declarations will create global variables which is bad!
more about this
Using the this
reference in a constructor function is exceedingly important if you want to add properties to the current instance. Without using this
, you only create a variable (which is not the same as a property) and as mentioned, if you don't use the var statement either, you create global variables.
function Person(){
name = 'Mary'
}
var p = new Person();
alert(p.name); // undefined, did not use 'this' to assign it to the instance.
alert(name); // 'Mary', boo, it created a global variable!
Use this!
function Person(){
this.name = 'Mary'
}
var p = new Person();
alert(p.name); // 'Mary', yay!
alert(name)l // undefined, yay!
Note, anything assigned to an instance through the function constructor CANNOT BE INHERITTED unless you assign it to the prototype and overwrite it again in the function constructor to make it an owned property.
When you create a new instance of through a function doubling as a constructor, actually the following happens.
pseudo code:
copy Person.prototype as person
invoke Person function on person
return person
Actually, this is what happens in every classical language when you create an instance of a class. But the main difference in JavaScript, is that it's not encapsulated inside a nice Class statement. Originally JavaScript didn't even have function constructors but where added on later because SUN demanded they wanted JavaScript to be more like Java.
Object literals
The alternative for function constructors for objects that carry only intrinsic data and no methods are object literals.
var Mary = {
firstName: 'Mary',
lastName: 'Littlelamb'
};
Which is the prefered way of declaring intrinsic objects rather then:
// do not ever do this!
var Mary = new Object();
Mary.firstName = 'Mary';
Mary.lastName = 'Littlelamb';
With object literals in your skill set, you can create a factory pattern for intrinsic data objects using the module pattern (which is usually for singletons).
var createPerson = function(firstName, lastName){
return {
firstName: firstName,
lastName: lastName
}
}
var Mary = createPerson('Mary', 'Littlelamb');
This achieves some comfortable encapsulation, but can only be used for intrinsic data objects.
Another thing you can do with Object literals and JavaScript is delegation, which should be prefered.
var personMethods = {
speak: function(){
alert(this.firstName + ' says: "Hello world!"');
}
};
var Mary = {
firstName: "Mary",
lastName: "Littlelamb"
};
var Peter = {
firstName: "Peter",
lastName: "Crieswolf"
};
personMethods.speak.apply(Mary); // alerts 'Mary says: "Hello world!"'
personMethods.speak.apply(Peter); // alerts 'Peter says: "Hello world!"'
Why should this be prefered? Because it keeps your objects minute and readable, even prototypical references take up memory and when using inheritance and 'subclassing' you end up with child instances that have lots of unused method references. Delegation is always better.