Object.create

ref – https://stackoverflow.com/questions/62378057/what-is-the-difference-between-object-assignment-and-object-create

Object.create(param) creates an empty object, with its __proto__ pointing to “param”. That way, the empty object can inherit properties from param.

We’ll demo this by first creating a literal object with “person” variable referencing it.

Now, in JS, the base Object class is an object that has a prototype reference that points to an Prototype Object. Its Prototype Object then has a constructor reference pointing back to the Object class.

Every object created in Javascript, will have its reference __proto__ pointing to Object’s Prototype Object. This situation is shown in the diagram:

Notice Object’s Prototype Object has a __proto__ pointing to null. __proto__ is the reference that indicates which object you inherit from. Thus, since our base class Object is the parent class of every object, it does not inherit from anyone. Thus, its Prototype Object’s __proto__ will be null.

Our person object will have its __proto__ pointing to the Object’s Prototype Object. This means our object derives from Object.

Create empty object and inherit from person object

We create an empty object called me, that extends from the person object we just created.
We do this like so:

1) Object.create will create an empty object
2) It will then point the empty object’s __proto__ reference to our person object

For completion purposes, let’s just add property “name” and initialize it to “Matthew”.

Now, using the me object, we can access its inherited properties from the person object. The reason why we can call printIntroduction is because me’s __proto__ points to person. It is set automatically by Object.create.

Let’s check out what the me object looks like.

We’ve accessed the function printIntroduction through me. Now let’s access the property isHuman.

Extending an Object

Previously, we’ve extend a literal object. Now, let’s extend a function object so that when we instantiate it by using new, all the instantiations will have the same inheritance.

First, let’s create a function called CoolPerson.

Basically, CoolPerson is a function object. This function object has a prototype reference to another Object (CoolPerson Prototype Object) that houses all a lot of properties and functions. It includes the constructor, which points back to function CoolPerson, and also a __proto__ that points to Object’s prototype object.

Let’s verify by logging CoolPerson, and its references.

console.log(CoolPerson) // [Function: CoolPerson] or f CoolPerson

Check out the output to make sure everything checks through.

Re-point prototype, creating a constructor and pointing it to the correct function

Previously, from above, we created a person object. It is a literal object that derives from base Object’s prototype.

When you try to access ‘constructor’, it will first see that person itself does not have a constructor property. We use hasOwnProperty to do this. However, when we do access the constructor, we see that it points to the default Object. This is because person uses its inheritance via __proto__ and finds that inheriting from Object’s Prototype Object, it does have a constructor property. This constructor property points to native Object.


> person
{isHuman: false, printIntroduction: ƒ}
> person.hasOwnProperty(constructor)
false
> person.constructor
ƒ Object() { [native code] }

1) Thus, first we need to repoint our prototype to person. What this means is that any instantiations created with “new” will inherit from peron.
2) we then need to create a property called constructor and attach it to person. This is so that the instantiations of CoolPerson will display their correct type. If you don’t do this, the instantiations will have type “Object”, instead of type “CoolPerson”.

Now, we can instantiate c. We are able to use property name from its original definition, and also access inherited properties from person object, such as isHuman, and printIntroduction.

Instantiation using inherited functionalities

The diagram for function CoolPerson that inherits from person object looks like this:

You’ll notice that an instance of CoolPerson will always inherit from the person object via its __proto__ reference. When a function definition in the person object accesses the ‘this’, the ‘this’ refers to the instance itself.

When instance c was made from function CoolPerson, it copies all the properties, including ‘name’. Thus, instance c has its own name. Once it access the singleton person object and sees this.name, it knows that this refers to the instance itself. And looks to see if there is a name property in the instance. It does, and hence it will use the name property in the instance.

Another Example

Connecting Hierarchy

Say we want to extend Person.
1) Create Student function object
2) const protoObj = Object.create(Person.prototype) // this creates an object with proto pointing to Person.prototype
3) Student.prototype = protoObj
4) protoObj.constructor = Student

So now when you create an instance say