2

When I execute the code:

console.log(Function.prototype);

It returns:

function Empty() {}

(At least in Chrome)

Why exactly is this? I was under the impression that prototypes were almost always straight-up object literals, and that seems to be the case almost everywhere else I've checked. I'm curious as to why Function.prototype resolves to something different.

Steve Kwan
  • 21
  • 1
  • you can assign a function to an object prototype , since functions are objects. , you can do F=function (){} , G=function (){}, G.prototype=F, console.log(G.prototype)//returns function(){} – mpm Feb 18 '13 at 06:13
  • Yeah, but the default prototype for newly created functions is an object literal. I'm just curious as to why for Function, it appears to be different. – Steve Kwan Feb 18 '13 at 06:16

2 Answers2

2

Because that is what ECMAScript 5 requires.

15.3.4 Properties of the Function Prototype Object

The Function prototype object is itself a Function object (its [[Class]] is "Function") that, when invoked, accepts any arguments and returns undefined.

Most (or all?) other native constructors have prototypes defined as the same type of object that is produced.

Considering that the prototype object holds the methods for that type, it makes sense that those methods should function properly when called on that object.

Community
  • 1
  • 1
the system
  • 9,244
  • 40
  • 46
  • Thanks! Is there any specific reason why it has to be that way? Some sort of structural thing that wouldn't work if Function.prototype were just an object literal? Or is it just a convention thing? – Steve Kwan Feb 18 '13 at 06:10
  • @SteveKwan: I just updated with a possible reason. Since the prototype object carries the methods for that type, it makes sense that those methods should function properly if invoked on that object. – the system Feb 18 '13 at 06:11
  • I see. So it's not so much that it's required for JavaScript to function, but more so that in the off chance someone messes with the prototype directly, it behaves the way they'd expect. – Steve Kwan Feb 18 '13 at 06:12
  • @SteveKwan: Right. In normal use it wouldn't really matter what type of object it is. – the system Feb 18 '13 at 06:16
  • @SamPinkus: Regarding that answer, first `__proto__` is not part of the ECMAScript standard. It's a non-standard add-on by some (not all) implementations. And with respect to the internal `[[Class]]` property, it isn't inherited from the prototype chain. It's directly included on each object *(internally)*. So they could have made the prototypes as plain objects, and the objects created from the constructors would still be identifiable using the internal `[[Class]]`. – the system Feb 18 '13 at 07:23
  • @SamPinkus: Yes, detailed at [Properties of Function Instances](http://es5.github.com/#x15.3.5), each instance is assigned the `[[Class]]`. – the system Feb 18 '13 at 15:53
0

Firstly note the actual prototype of an object, as in the thing an object inherits behavior from, is stored in its __proto__ property (in most implementations - thx @the system). The Function object's "prototype" property is its own __proto__, which is special inbuilt function literal singleton object function(){} (which Chrome's console.log() must print as function Empty() {} for whatever reason but its the same thing). Since all functions are objects (but not all objects are functions) this object's __proto__ is another special inbuilt literal singleton object [object Object]. [object Object] __proto__ is null. [object Object] is the root of the prototype chain.

Examining the output of this shows how things are arranged (runnable from a command line interpreter).

print( Function.prototype === Function.__proto__ );
var f = new Funtion();
print( f.__proto__ === Function.prototype );
print( f.__proto__ );
print( f.__proto__.__proto__ );
print( f.__proto__.__proto__.proto__ );

Now, built-in JavaScript objects have a property called "class". This property is immutable and set by the JavaScript engine itself. The class is used by JavaScript for special internal purposes. Javascript needs to know this, so it knows Function objects can be invoked for example (as implied in the link from a previous answer given by @thesystem - http://es5.github.com/#x15.3.4). From the spec:

"The value of the [[Class]] internal property is defined by this specification for every kind of built-in object. The value of the [[Class]] internal property of a host object may be any String value except one of "Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", and "String". The value of a [[Class]] internal property is used internally to distinguish different kinds of objects. Note that this specification does not provide any means for a program to access that value except through Object.prototype.toString (see 15.2.4.2)." - http://es5.github.com/#x8.6.2

The "class" of the Function object's prototype AKA function(){} is "Function". The class of Function is also "Function". When a new object is created Javascript sets its class property directly, based on the class property of its constructor, and this is immutable for the life of the object.

spinkus
  • 7,694
  • 4
  • 38
  • 62