After reading this documentation: http://es5.github.io/#x4.2.1
I was confused by the two prototype references on CF, and by this statement:
The property named CFP1 in CFp is shared by cf1, cf2, cf3, cf4, and cf5 (but not by CF)
Much of the literature on Javascript points out that functions are first class objects, and as such I'd expect to be able to set their implicit prototype reference like an object to achieve prototypal inheritance (disclaimer: I don't actually know what I'd use this inheritance for, but it occurred to me to see if it's possible). Can I set this implicit prototype on a function, or will it always point to Function.prototype (I'm assuming that's the default). And why does Function have both explicit and implicit prototypes? Also do any other types in Javascript have both explicit and implicit prototype references or is Function unique in this regard?
Consider the diagram from the specification, and the code below it, which tries to reproduce what's going on:
function CF() {}; // the constructor
CF.P1 = 'foo'; // P1 is an own property of the constructor; P2 is the same
var CFp = { CRP1: 'bar' }; // for now, just an object, with a CRP1 property
CF.prototype = CFp // set CFp as the 'explicit prototype property' of CF;
// only constructors have such a property
var cf1 = new CF(); // an instance;
var cf2 = new CF(); // another instance; cf3..cf5 are constructed the same way
Object.getPrototypeOf(cf1); // CFp; this is the 'implicit prototype link' from cf1 to CFp;
// put another way, CFp became the [[Prototype]] of cf1
You said you were confused by this sentence: the property named CFP1 in CFp is shared by cf1, cf2, cf3, cf4, and cf5 (but not by CF). Consider this:
cf1.CRP1; // 'bar' - found on CFp through cf1
cf2.CRP1; // 'bar' - found on CFp through cf2
CF.CRP1; // undefined
So what that sentence means that you can access the contents of CRP1
from cf1..cf5
, but not from the constructor CF
(remember, functions/constructors are objects too, thus they can have properties). And that's because CFp
(the "owner" of CRP1
) is not the [[Prototype]]
of CF
, it's just the value pointed by the CF.prototype
property. The prototype
property only exist in function objects, and is used solely to define the [[Prototype]]
of instances created by invocations of the function is invoked as a constructor (like in new CF()
). The fact that both [[Prototype]]
and prototype
read as "prototype" is the source of great confusion – and maybe part of what is confusing you; hopefully, it's less confusing now. With that in mind, I'll try to shortly answer your other questions.
Much of the literature on Javascript points out that functions are first class objects, and as such I'd expect to be able to set their implicit prototype reference like an object to achieve prototypal inheritance [...].
In ES5 there is no way to directly set the implicit prototype reference (or [[Prototype]]
) of an existing object, except for the non-standard __proto__
property. What you can do is create new objects with a given [[Prototype]]
. You can do that with var obj = new ConstructorFunction()
, where the [[Prototype]]
of obj
is ConstructorFunction.prototype
, or with var obj = Object.create(someOtherObj)
, where the [[Prototype]]
of obj
is someOtherObj
. The later versions of the language introduced Object.setPrototypeOf
to do that, but its use is discouraged for performance reasons[still current? citation needed].
Can I set this implicit prototype on a function, or will it always point to Function.prototype (I'm assuming that's the default).
Yes, with __proto__
or Object.setPrototypeOf
. But usually you shouldn't.
And why does Function have both explicit and implicit prototypes? Also do any other types in Javascript have both explicit and implicit prototype references or is Function unique in this regard?
Function
("the Function
constructor") is just a function, and as any other function it has a prototype
property; it's also an object, and as (almost) any other object is has a [[Prototype]]
object. There are standard constructors for other types too, like Object
, String
, Array
, Boolean
, Number
. They're all functions, and have both a prototype
and a [[Prototype]]
.