Elementary, My Dear Watson!
The very first thing we might want to do, in order to make our research, discovery, and piece of programming history useful, is creating a couple of shortcuts that will let us easily analyze the code and the current story:// retrieve the first inherited prototype var $proto = Object.getPrototypeOf; // retrieve all own properties, // enumerable or not, ES5 stuff ! var $props = Object.getOwnPropertyNames;Why do we need that? Because almost everything is an
instanceof Object
in JavaScript world, which simply means, and we'll see this later on, that Object.prototype
is inherited all over!Well, Almost!
SinceObject.prototype
is an object, there's no way this can be called as a function, right?No doubts
Object
inherits at some point its own prototype but who added apply
, bind
, call
, constructor
, length
, name
, and that funny toString
behavior in the middle?Not Function !
That's correct,Function
has nothing to do with that. Function
actually inherited those properties and redefined some behavior such name
and length
.Is the
Object
constructor instanceof
the Function
one ? Yes!
Is the Function
object instanceof
Object
? Yes again and trust me: there's no real WTF!
Object instanceof Function; // true Function instanceof Object; // true
The First Object Ever: null
This is the prototype of the prototypes, if we check$proto(Object.prototype)
the result will be null
indeed.As summary, the very number one object to inherit from, possible in fact as
Object.create(null)
instance too, is this reserved static keyword everybody ever complained about because it returns "object"
instead of "null" under typeof null
inspection.Can we start seeing that being the mother and the father of everything we use in JS world, "object" is kinda the best
typeof
we could possibly expect?There Are Two Suns!
This is the lie we all believed until now,Object.prototype
is where everything inherits from ... well, brace yourself, an hidden Empty
object is part of this game!Chicken or egg, who came first? You cannot use much philosophy in programming, you have to solve stuff and give priority or order to the chaos represented by requirements and/or implementations about specs, right? :D
So here the chain you have always wondered about:
null < Object.prototype < Empty < Function ObjectWait a second ... how can
Object.prototype
then exists before Object
is even created ?So here the secret about JavaScript, the elephant Classic OOP guys keep ignoring in the room:
Object.prototype
is just an object that's inheriting from null!The fact we call it
Object.prototype
is because that's the only way to reach it via JavaScript but here how you could look at the story:
null: the omnipotent entity, the origin of everything, the daily Big Bang that expands on each program! prototype: like planet Earth, the origin of all our user definable problems Empty: the supreme emptiness of everything, meditation over "dafuq just happened"! Function: somebody has to do actually something concrete: the slave! Object: somebody has to take control of everything: the privileged king!Are we done here? ... uh, wait, I knew that!
"The time has come," the Object said,
"To talk of many things:
Of keys and __proto__ and magic things
Of prototype and kings
And why that Empty is boiling hot
We show that pigs have wings."
The Object.prototype we set!
As prototype itself!
Object.prototype = prototype;
The instanceof Operator
As shortcut,instanceof
is freaking fast compared with any user definable interaction with the code.In few words, if you want to know if
ObjA.prototype
object is in the prototype chain of objB
, you better objB instanceof ObjA
rather than ObjA.prototype.isPrototypeOf(objB)
, I mean .. really, check performance here!So, once we get the pattern followed by
instanceof
, it's easy to do the math here:
Object instanceof Object // means Object.prototype.isPrototypeOf(Object)Remember the hierarchy?
Object
inherits from Empty
, and Empty
inherits from prototype
so, of course Object
inherits from prototype
, it's transitive!
Object instanceof Function means Function.prototype.isPrototypeOf(Object)Again,
Object
inherits from Empty
so obviously Function.prototype
, which is Empty
indeed, is one of the prototype
of Object
^_^Who Defined The prototype Behavior?
This is the tricky one ... so,prototype
is not even invocable and as such it cannot be used as constructor. Actually, neither can Empty
, since it cannot be used as constructor too ... so new Empty
will throw, watch out!In fact,
Empty
introduces the [[Call]]
paradigm, inherited by all primitive constructors such Array
, Object
, Function
, Boolean
, but is not inheritable from user defined objects, or better, you need to create a function(){}
object to have that special behavior inherited from Empty
and the prototype
inherited from Function
.
Empty.isPrototypeOf(function(){}); // true
Which prototype Behavior ?
Well, this is the main point aboutinstanceof
and isPrototypeOf()
, the prototype
behavior defined in the Function
object, the only object adding that prototype property defining its behavior in the program!
$props(Empty) ["apply", "bind", "call", "constructor", "length", "name", "toString"] $props(Function) ["length", "name", "prototype"] // could be more in other engines
The Last Troll Ever!
It's clear thatEmpty
introduced the constructor
property too and guess what happened there?
"The time has come," the Empty said,So that
"To talk of many things:
Of constructor and new toString
Of call, bind, apply and kings
And why that caller is boiling hot
We show that pigs have wings."
The Empty.constructor we set!
The Function we just let
Function.prototype(aka:Empty).constructor === Function
is true
:)
Last, but not least, if you think as "Empty function"
Empty
is fast, just check this bench and realize that it could be the slowest function ever invoked!
So, here is the story of the root of all amazing things we can enjoy on daily basis in this Internet era, could you imagine?
No comments:
Post a Comment