I've come across the following diagram which looks rather messy.
So here comes my question:
Why does JavaScipt have separate Function and Object function objects (instead of for instance simply having everything defined at the top level by the user point to a single prototype object Root, and with the prototype of Root pointing back to Root, which would seem to be a much simpler and more intuitive design)?
Thanks.
Sorry for my misunderstanding. Now I realize:
JavaScript has primitive data types and objects. The primitive data types are
boolean, number, string, null, and undefined. When needed the first three of
these are treated as instances of Boolean, Number, and String. Everything
else is an object, including functions, arrays, regular expressions, and
dates. Functions may be used as constructors or as ordinary functions.
When a function is used as a constructor it can be used to instantiate
object instances via the new operator. The prototype of the instantiated
instance (accessed via the __proto__
property) is set to the constructor's
'prototype' property when the instance is instantiated. The __proto__
members are used to resolve properties via the prototypical inheritance chain.
Since functions are more specialized than objects there is a Function.prototype object stuck in the prototypical inheritance chain between functions and the top-level Object.prototype object. The Function and Object constructor functions should themselves not normally be needed since we can make use of the function keyword and object literals directly.
A constructor function can only have one prototype (at any given time). When an object is constructed, it becomes related to the prototype object referenced by its constructor. Function objects (and String objects and Date objects, etc) have prototypes with different sets of properties. All objects have prototype chains that eventually go back to the Object prototype.
The case with Function instances is even more distinct: the constructed objects are functions. The Function constructor (which is part of the native runtime) gives the constructed object internal properties that make it possible for the runtime to access the block of code associated with functions. Specifically (this is all from section 13.2 of the spec:
[[Call]]
internal property is set to the value of the parsed function body (the code of the function)[[Construct]]
internal property is also set to the function body (and that's why all functions can be used as constructors)[[HasInstance]]
internal property is made to refer to the internal code that implements section 15.3.5.3, which makes instanceOf
workand similarly for internal properties [[Code]]
, [[FormalParameters]]
, [[Scope]]
, and others. In other words, a function object is iternally special in a lot of ways. In its relationship to the Function prototype, however, it's not really special. The function prototype is consulted during the process of property lookup on the function object itself. For example, when resolving an expression like this:
var bound = function() { alert(this); }.bind("hello");
the runtime has to locate the property "bind". It won't be found on the function object itself, but it will be found on the prototype.