What is the correct output (meaning correct by the ECMA standard) of the following program?
function nl(x) { document.write(x + "<br>"); }
nl(Function.prototype);
nl(Function.prototype.prototype);
nl(Function.prototype.prototype == Object.prototype);
nl(Function.prototype.prototype.prototype);
Chrome and IE6 agree in saying:
function Empty() {}
null for Chrome / undefined for IE6
false
and then crashing.
Mozilla outputs:
function () { }
[object Object]
false
undefined
Are either of these correct? It seems that the Mozilla one does better, but that the best output is
function () { }
[object Object]
true
undefined
Function.prototype
From ECMAScript Language Specification:
15.3.3.1 Function.prototype
The initial value of Function.prototype is the Function prototype object (section 15.3.4).
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. The value of the internal [[Prototype]] property of the Function prototype object is the Object prototype object (section 15.3.2.1).
It is a function with an “empty body”; if it is invoked, it merely returns undefined. The Function prototype object does not have a valueOf property of its own; however, it inherits the valueOf property from the Object prototype Object.
I get this output:
Chrome and IE7 has named their functions, Opera and IE7 tells you that it will not reveal the implementation. They all agree on this:
nl(typeof Function.prototype); //function
Compare this to:
nl(typeof Object.prototype); //object
nl(typeof Array.prototype); //object
nl(typeof String.prototype); // object
Function.prototype.prototype
I get undefined from Opera and IE7, null from Chrome and [object Object] from FF3. Who is right? Since "The Function prototype object is itself a Function object" shouldn't it be a circular reference to itself? To avoid the circular reference they have chosen different ways. I don't know if there is a standard for that or if it is up to the implementation, but I think an Object is right. Btw, here you see the difference between the internal [[prototype]] and the public prototype in action, like you asked in an earlier question!
Function.prototype.prototype == Object.prototype
This is false because it isn't the same object. See above.
Function.prototype.prototype.prototype
Only FF will give you an answer because of their implementation of Function.prototype.prototype returns an Object.
I agree that your proposed output looks more logic.
They do agree on this:
nl(Object.prototype); // [object Object]
nl(Object.prototype.prototype); // undefined
What you're doing here isn't really walking the prototype chain - this question might help you understand what is actually going on. I didn't bother to check the ECMA spec, but here is my take on the issue:
Function is the constructor of function objects
Function.prototype is the prototype from which all function objects inherit - it might contain properties like call and apply which are common to all Function instances; the implementations you checked were consistent in that it is implemented as a function object itself (as some pointed out, the ECMA specification requires this)
Function.prototype.prototype does't really make much sense, but as Function.prototype is implemented as a function object (which could possibly be used as a constructor), it should at least exists; objects which are created using Function.prototype as constructor would inherit its properties - but as there should be no reason to do something insane like this, setting it to null, undefined or an empty object is reasonable
Function.prototype.prototype.prototype will in all likelyhood be undefined: as we have seen before, Function.prototype.prototype should be something without properties (null, undefined or an empty object) and definetely not a function object; therefore, its prototype property should be undefined or might even throw an error when trying to be accessed
Hope this helps ;)
To answer your question directly: Mozilla is right. Not only because Brendan Eich works for Mozilla, but because this is the only right way to do it. Let's go over details:
prototype
property to be used to construct objects.Object
nor Object.prototype
.Let me elaborate on the last statement. If it is false, we can recreate function in the user code like that:
// we re-creating the function!
// our function constructor
var Fun = function(){ /*...*/ };
// let's chain the prototype
Fun.prototype = new Object();
// do we have a function now? let's fund out
var fun = new Fun();
console.log(fun.length); // undefined
fun.call(null); // fail
fun.apply({}, [1, 2, 3]); // fail
// nope
We can observe that new Object()
doesn't define new methods nor properties and can try using Object.prototype
directly with the same result.
Summary: the prototype of the function is not Object
nor Object.prototype
. It is some very special object. This is one more reason why we cannot re-create a function in the user code.
EDIT: for more details on prototypes look at this answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With