Javascript Prototype

https://javascript.info/prototype-inheritance

Prototype, function, and New

https://scotch.io/tutorials/better-javascript-with-es6-pt-ii-a-deep-dive-into-classes

When you call a function with new, four things happen under the hood:

  • A new object gets created (let’s call it O)
  • O gets linked to another object, called its prototype
  • The function’s this value is set to refer to O
  • The function implicitly returns O

We can also rewrite our Food function to work without the new keyword:

Everything is straightforward, except the setPrototypeOf.

Prototype Inheritance

Under normal circumstances, all objects in JavaScript — including Functions — are linked to another object, called its prototype.

If you request a property on an object that the object doesn’t have, JavaScript checks the object’s prototype for that property. In other words, if you ask for a property on an object that the object doesn’t have, it says: “I don’t know. Ask my prototype.”

This process — referring lookups for nonexistent properties to another object — is called delegation.

The output from our toString calls is utterly useless, but note that this snippet doesn’t raise a single ReferenceError!
That’s because, while neither joe or sara has a toString property, their prototype does.

When we look for sara.toString(), sara says, I don’t have a toString property. Ask my prototype.
JavaScript, obligingly, does as told, and asks Object.prototype if it has a toString property. Since it does, it hands Object.prototype’s toString back to our program, which executes it.

It doesn’t matter that sara didn’t have the property herself — we just delegated the lookup to the prototype.

In other words, we can access non-existent properties on an object as long as that object’s prototype does have those properties. We can take advantage of this by assigning properties and methods to an object’s prototype, so that we can use them as if they existed on the object itself.

Even better, if several objects share the same prototype — as is the case with joe and sara above — they can all access that prototype’s properties, immediately after we assign them, without our having to copy those properties or methods to each individual object.

This is what people generally refer to as prototypical/prototypal inheritance — if my object doesn’t have it, but my object’s prototype does, my object inherits the property.

In reality, there’s no “inheritance” going on, here.

In class-oriented languages, inheritance implies behavior is copied from a parent to a child.

In JavaScript, no such copying takes place — which is, in fact, one of the major benefits of prototypes over classes because we can dynamically switch to different prototypes and the prototype would “delegate” properties to those objects.

Setting an Object’s Prototype

The function, Object, has a property, called .prototype, which points to any object Object.prototype that you want.

The object, Object.prototype, has a property, called .constructor, which points to a function (Object). Keep in mind that this Object.prototype.constructor property is just a public property of Object.prototype. It is not used in any way in the construction of new objects or resolution of property names.

basic_prototype

You can also change the property to reference other objects. Rabbit.Property references an object. Any object created with new will now have their [[Prototype]] reference object {eats: true}. When we change Rabbit.Property to an empty object {}, further new objects created will then have their [[Prototype]] reference the new prototype object.

changing_properties

Prototype properties will over shadow objects that delegate from them

When both your object and its prototype has the same property, the prototype will have precedence.

Now we add the function “cook” to our prototype, in which we can then use.

Further Reading – Prototype Chain Details

In programming, we often want to take something and extend it.

In JavaScript, objects have a special hidden property [[Prototype]] (as named in the specification), that is either:
– null
– references another object. (all properties/methods of that object will be inherited)

That object is called “a prototype”:

When we want to read a property from object, and it’s missing, JavaScript automatically takes it from the prototype.

The property [[Prototype]] is internal and hidden, but there are many ways to set it.
One of them is to use __proto__, like this:

// So if animal has a lot of useful properties and methods,
// then they become automatically available in rabbit.
// Such properties are called “inherited”.

__proto__ IS NOT the same as [[Prototype]].

[[Prototype]]’s getter/setter is __proto__

If the subclass does not have the property/method, then JavaScript automatically takes it from the parent class.

Then, when console.log tries to read property rabbit.eats (**), it’s not exist in rabbit, so JavaScript follows the [[Prototype]] reference and finds it in animal (look from the bottom up).

Here we can say that animal is the prototype of rabbit or rabbit prototypally inherits from animal.

So if animal has a lot of useful properties and methods, then they become automatically available in rabbit. Such properties are called “inherited”.

Inherited Method

If we have a method in animal, it can be called on rabbit:

Longer Prototype Chain

getter setter in prototype inheritance

An interesting question may arise in the example above: what’s the value of this inside set fullName(value)?
Where the properties this.name and this.surname are written: user or admin?
The answer is simple: this is not affected by prototypes at all.
No matter where the method is found: in an object or its prototype. In a method call, this is always the object before the dot.
So, the setter actually uses admin as this, not user.

That is actually a super-important thing, because we may have a big object with many methods and inherit from it.
Then we can run its methods on inherited objects and they will modify the state of these objects, not the big one.

For instance, here animal represents a “method storage”, and rabbit makes use of it.
The call rabbit.sleep() sets this.isSleeping on the rabbit object:

If we had other objects like bird, snake etc inheriting from animal, they would also gain access to methods of animal. But this in each method would be the corresponding object, evaluated at the call-time (before dot), not animal. So when we write data into this, it is stored into these objects.

As a result, methods are shared, but the object state is not.

In JavaScript, all objects have a hidden [[Prototype]] property that’s either another object or null.

We can use obj.__proto__ to access it (there are other ways too, to be covered soon).

The object referenced by [[Prototype]] is called a “prototype”.

If we want to read a property of obj or call a method, and it doesn’t exist, then JavaScript tries to find it in the prototype list, from its immediate parent, and on up.

Write/delete operations work directly on the object, they don’t use the prototype (unless the property is actually a setter).

If we call obj.method(), and the method is taken from the prototype, the obj’s “this” still references the obj. So methods always work with the current object even if they are inherited.

Special

rabbit.jumps overrides its prototype reference’s jumps. Thus we get true.
Then we delete rabbit.jumps. This deletes the rabbit’s jumps (the one that overrides the prototype’s jumps).
Since the jump that overrides the prototype’s jump is now deleted, “rabbit.jumps” then refers to its prototype’s jumps, which comes out to be null.
We delete animal.jumps.
Since rabbit has no jumps, and then it goes to its prototype and sees no jumps, then jumps would be undefined, because undefined is assigned to anything that is undeclared.

Including Prototype, properties that describe the state of a particular object, is written into the object

Speedy derives from hamster.
lazy derives from hamster.
Stomach, since it is a property that describes the state of an object, is written into itself.
Thus, that’s why when Speedy calls stomach, it does this:

1) accesses this.stomach, stomach here belongs to hamster.
2) calls push on this.stomach. It pushes a string into array stomach.

When Lazy calls stomach, it does the same thing as above.

Thus, that’s when a parent class has a property that describes the state of an object, all its deriving objects will share that property.

In order to fix this you can do 2 things:

1)
Essentially, we work on “this”, the child object that is deriving.
Then, we create a new array with the food name, and references the child object’s property to it.

2) Instead of working on “this” in the parent object, we simply put all methods to be shared by “this” in the parent object, and leave the stomach property for its children like so:

__proto__ and prototype usage

http://sporto.github.io/blog/2013/02/22/a-plain-english-guide-to-javascript-prototypes/