It is important to build a mental model of how Javascript objects are implemented: if you're coming from a C++ background then consider this possible model
All objects in javascript are of the same class, the class "Object"
Each object is defined with something like
class Object {
std::map<std::string, Object *> attributes;
};
and this means for example that
The set of attributes is not fixed, you can add attributes at runtime to a specific object instance
Inheritance doesn't work like in C++
Each object has a special attribute named constructor
The constructor
of an object is the function that was used to instantiate the object. For example if you write
function Person(first_name, last_name) {
this.first_name = first_name;
this.last_name = last_name;
}
then executing
var p = new Person("Andrea", "Griffini");
alert(p.constructor === Person);
Will display "true" in a message box.
The constructor is an object too
The constructor
of the constructor
is Function
, and as you probably guess it's an object too, with itself as constructor.
A constructor has a special attribute named prototype
This special attribute is what allows inheritance among other things. The rules followed by Javascript are simple: when accessing a attribute attr
of an object x
- if the instance
x
has itself the requested attribute then the value is returned
- otherwise
x.constructor.prototype
is looked up for attr
instead of x
The second step is also recursive, meaning that if x.constructor.prototype
doesn't have the attribute either then x.constructor.prototype.constructor.prototype
is searched instead and so on.
When setting an attribute however Javascript simply sets it in the instance, not following the constructor.prototype
chain.
This explains the apparently strange behavior...
function Person(first_name, last_name) {
this.first_name = first_name;
this.last_name = last_name;
}
Person.prototype.display = function() {
return this.first_name + ", " + this.last_name;
}
var p = new Person("Andrea", "Griffini");
var q = new Person("John", "Smith");
q.display = function() {
return "... not sure ...";
}
alert(p.display()); // Says "Andrea, Griffini"
alert(q.display()); // Says "... not sure ..."
this
is a run-time concept in Javascript
this
can be seen simply as a global variable that is automatically set by Javascript: more specifically when you write
obj.method(...);
the method
attribute is looked up as usual, but before being called this
is set to obj
and restored to its current value once the method returns; in other words what happens is more or less:
// Not real code, just to show the concept
var old_this = this;
this = obj;
method(...);
this = old_this;
and it also means that the two fragments
// First case
var f = obj.method;
f();
// Second case
obj.method();
are not equivalent, because in the first case the code of the method will be executed with this
being "the global object", while in the second case this
value will be obj
during the execution of the method code. The this
magic only happens if you call the result of an attribute lookup... even just using [obj.method][0]()
is not the same as obj.method()
because this
will be the array (that has been looked up for the attribute 0
) during the execution of method code.
This is not the whole truth
This reply only wants to give you a rough description of how things more or less are working in Javascript and of course they're not the truth but I think just these few ideas should be able to take you far enough into Javascript programming.
For the whole truth you'd need to read quite a bit more.