Further to the great explanations in this thread, it is interesting to see what happens under the hood. The ECMAScript specification (where Javascript is based) defines a global object. This is implemented differently in different execution environments. In your typical browser, it is the window
object while in Node.js it is the root
object. Every function defined "in the wild" (not attached to a user created object) will become a property of the global object. In Node.js you can try:
> function Test() {};
> root.Test
[Function: Test]
Now, the this
variable points to the object that the function is a member of. So in the example above:
> function Test() {
... console.log(this === root);
... };
> Test()
true
Same goes for your function Terminal
. If you run it, this
will point to the global object which is of course not an instance of Terminal
!
When calling a function using the new
operator, an object is returned which will have access to a property called constructor
that will point back to that function. It is something equivalent to:
> var instance = {};
> instance.constructor = Terminal;
> instance.constructor();
So, when the conditional fails and the Terminal function is run through the new Terminal()
line, this
will point to a newly created instance which is of type Terminal!
If you want to get more technical, instance
does not have a constructor
property itself. It is instead linked (via the prototype chain*), to a private object** (created by the runtime) that has a constructor
property pointing to the Terminal function. That private object is pointed back to by the function through a prototype
property. D.Crockford presents this in pseudocode as follows:
Terminal.prototype = {constructor: Terminal};
Again, this is only when you call the function with new
.
* If a property is not found, the object will look it up at the object pointed to by the __proto__
property.
** (imagine something like an object called _Terminal
that you cannot access by name)