About JavaScript
In JavaScript, variables are not typed. Every variable can contain an object reference, a string value, a number value, a Boolean value, a null value, or an "undefined" value.
Objects are collections of named member variables, and nothing more. There are no constant members, nor are there any special "function members". All of the member variables are public, meaning any code which has a reference to the object can read and write any of its member variables.
Members, which are named variables, can be added to or removed from any object at any time. There is no native object-typing system in JavaScript. Any normal object can ultimately be fully transformed into any other kind of normal object, through member addition and removal.
Functions as such are a special (abnormal) kind of object which, in addition to its members, has code, which can be invoked with arguments. The code of a function has no name, and it is immutable -- you can't change it once it is set.
Objects in JavaScript are values, references to which can be stored in variables. So each object can be referenced by several variables, and thereby be accessed through different names. Since functions are objects, they only (really) have names by virtue of being assigned to variables.
A function, when invoked by means of a member variable of a particular object, is implicitly passed an extra, special argument called "this", which refers to the object which owns the member variable. The same function can be referred to by member variables of two different objects, and it will be passed a different value for "this" depending on which object's member variable it is called through.
In this way, a function can access the other member variables of the object which it was invoked through, without needing the object reference to be explicitly passed to it.
There are no classes in JavaScript. So you don't need a class in order to create an object. You just use an object literal, which specifies the object's initial variables with their initial values :
{
foo : "1",
bar : "2"
bar : "2"
}
An object literal is an expression, which, whenever evaluated, constructs a new object.
To re-use an object, you need to assign the object to a variable:
var a = {
foo: "1",
bar: "2"
bar: "2"
};
So, objects are never declared. Variables are declared, and objects are assigned to them.
Functions, however, can be declared:
function fizzle()
{
};
{
};
But there's generally little or no benefit to declaring them, as the above code (except for a minor detail) is in effect identical to this code:
var fizzle = function () {
};
};
In both cases, a variable called fizzle is created, and a reference to an empty function is assigned to it. The only difference has to do with a special "name" member of the function. In the first case, it is set to "fizzle", in the second case, it is set to the empty string (the "name" member is helpful in some debug environments).
So it's best to think of functions like objects. You don't declare them – you create them and store references to them. Just as with other objects, if you wish to re-use a function (which is created by the evaluation of a function literal), you must assign it to a variable.
Strictly speaking, objects (and functions, which are objects) are values. Later, we'll see that the same thing is true for arrays, which, like functions, are also a special (abnormal) kind of object. But our current discussion involves only functions and regular objects.
JavaScript is loosely typed. There's no typing system built into the language to support object types. If you are used to a language like C++ or ActionScript, where you can define your own object types (called "classes"), and have the language itself assure for you that you are only using, in any particular context, the right type of object, you are out of luck. In JavaScript, any object can be assigned to any variable.
It's hard to imagine, though, not thinking in terms of object types while writing your program. An object type tells you what type of object is valid in any particular context. Even if the language itself doesn't enforce this for you (before run-time, when, for example, you might accidentally pass, to a function, an object that doesn't have all the expected members), is there some aspect of JavaScript that can support you in your desire to think of objects as having a type?
The answer is yes. That aspect of JavaScript is called a function.
To understand this, we need to take a step back and ask, what is an object type? What would the type of an object be, in a language which provides no explicit support for object typing? Practically speaking, what do we mean when we are talking about the type of an object?
The type of an object regards what properties it has. Objects with different property sets are different types of objects. For instance a table object might have properties such as "legCount", "height", and "surface shape". A person object might have properties such as "name", "address", "political affiliation" etc. As well, objects have properties which are functions, which denote actions which either they can do, or which can be done to them. For instance, a person might have a "run" function or a "flatter" function, or a table might have a "flip" function, or a "provide support for" function.
So, an object type is a specific property set. When a particular function expects, as an argument, an object with a particular property set, it's implicitly expecting an object of a specific type.
Note that an object type is an expectation of what properties it has. An object type is a standard of class membership. Without having certain properties, it doesn't meet the standard.
It's natural, then, in JavaScript, to use a function to construct a new object with a desired set of properties -- the set of properties required for membership in a particular class.
JavaScript actually has special support for this kind of function, and calls it a constructor function.
Syntactically, constructor functions are no different from regular functions. All functions can make use of "this" to access the object which they are acting on behalf of. A constructor function is different, though, from most functions in that it assumes that this refers to an object without any properties yet, and it is primarily concerned with adding properties to the object this refers to.
This raises a question: how can you call a function, giving it an implicit object (this) to work on, if the function is not already referred to by a member of the object? In other words, if a constructor function expects an empty object as this, how can you call it without contradicting that assumption?
One answer (of several) is the new prefix. When you call a function with the new keyword in front of it, then the value of this inside that function refers to a brand new object, rather than whatever else it would have been. This lets you use the function to initialize an object from nothingness, assuring that the end result is an object with a specific property set.
So, a constructor function serves to initialize an object, guaranteeing that it becomes an object of a specific object type, or class.
To achieve inheritance, one constructor function can call another constructor function. For example:
var Base = function () {
// set up members for Base
}
var Derived = function () {
Base.call(this); // Derived inherits from Base (don't use "new")
// set up additional members for Derived.
// set up additional members for Derived.
}
var myBase = new Base();
var myDerived = new Derived();
Note that when this is done, you only use new once for each object. You don't use it when calling a superclass's constructor function with call.
This is the simplest form of inheritance in JavaScript, and it is called functional inheritance. It's "functional" in that you call a function to inherit another class's properties.