prototype is a singleton that is created for each class (by JS runtime), so that instances of the class can be constructed based on the in memory template. I call
prototype semi-OOP because it is not normal. For instance, this is how a
prototype based inheritance is programmed:
I will cover
prototype based inheritance in the next post. For now, we just grasp the idea of how things are different here.
prototype is not useful anymore? My answer is No, because it still largely exists in a large amount of existing code. For concrete numbers, if
grep -R prototype *|wc -l, at the point of time when I am writing, in Angular, the output shows there are 286 lines; in React, there are 405; and Vue, 756). As for me, I need to know
prototype to understand these 1447 lines of backbones. Last but not least, the frameworks are ordered alphabetically 😅.
In the following example, we first define a constructor (If you do not know what is a constructor in JS context, please ⬅ to my last post). Then we use it to create an object and examine the prototype(s).
An initial observation:
prototypeonly exists in a class (a.k.a., a constructor). If you need to access
class instance(a.k.a., an object),
__proto__is the way to go.
__proto__are just two sides of one coin. In technical words, they refer to the same instance, i.e., the singleton mentioned in the beginning of this text.
- the prototype of a class can be changed at runtime, and all the instances of this class are affected accordingly.
Moreover, a modification of
__proto__ of an instance can change the
prototype (definition) of a class, and all the sibling instances are affected in a cascade manner.
This operation is dangerous. It will cause side-effect and confusion in a project with reasonable complexity as the definition of a class can not be easily traceable. Hence I highly recommend considering
__proto__ final (in Java) or constant (in C++) and should be never touched.
If you really want to modify the behavior of an object, say, add a property, at least modify the object itself rather than
On the other hand, adding a property to a class effectively creates a static member (in other language term).
I would recommend this usage.
So the bright side of this feature is flexibility, empowered by that
__proto__s, etc. Let’s prove it in code.
Furthermore, Object is subdivided into two categories, first class objects and all other normal objects. Normal objects are just variables, which can be created, modified, assigned to other variables, and passed as arguments (or return value), all in runtime. Whilst first class object is the “platinum version” of object that unlocks extra privileges. Besides the operations listed above, first class object can be invoked (as a normal function); and it can be invoked to create normal objects (as a constructor). I think those extra privileges can explain from another perspective why first class object is attached one extra member property
Did I just said everything is object?
Even though a string literal is not an object, it contains
__proto__ that is an object?! So either string literal is an object, which is obviously not, or what I said in the last section is just bullshit.
It is not. What happens here is that a mechanism called automatic wrapping kicks in, which wraps the no-object (primitive) variables to its object counterpart , in this case, a String(), as required. Automatic wrapping can enable calling methods directly from primitives as well:
Same phenomenon happens: the runtime wrap the literal to
String() automatically and calls the
indexOf() method. And the rule applies to other primitive types (int, float) as well.
All sounds perfect until I tried this
var obj and
obj.__proto__ are objects according to the first two outputs. However, when I want to confirm if
obj.__proto__ is really an object, runtime gives me a
false. I hope I am not the first bloger who writes about things he is not sure himself, but if you have an answer, please let me know in the comments. It does not matter if you don’t, as
__proto__ is no-standard usage anyway.