Object Oriented Programming (Building blocks) - PintoGideon/Recursive-React-Tree-Component GitHub Wiki

OOP building blocks

let user1={
name:'Will',
score:3,
increment:function(){user1.increment++}
};

user1.increment();

Factory Functions

If we want to create an empty object, we use Object.create(null).

let user2=Object.create(null)  // user2={}
user2.score=3;
user2.name='Jim';
user2.increment=function(){
user2.score++
}

Our code is getting repetitive though. Let's abstract the repetitive functionalities.


function userCreator(name,score){
const newUser={};
newUser.name=name;
newUser.score=score;
newUser.increment=function(){
newUser.score++
}
return newUser
}

const user1= userCreator('Will',3);
const user2= userCreator('Tim',5);
user1.increment();

Hey, do you notice that the increment function performs the same functionality and we are storing it twice. It can be abstracted out even further. How can repeated functionality be shared between users? We don't want to manually add a feature on for each user.

Prototype chain

function userCreator(name,score){
const newUser=Object.create(userFunctionStore)
newUser.score=score;
newUser.name=name;
return newUser
}

const userFunctionStore={
increment:function(){this.score++},
login:function(){console.log('Logged in')
}

const user1=userCreator('Gideon',100);
const user2=userCreator('Amod',50);
user1.increment() //101
user2.increment() //51

Wait a minute !! The object that is returned does not appear to have the increment method on it? Under the hood there is a hidden property on the received object which has a wire to userFunctionStore.

{
name:"Gideon"
score:100
__proto__:userFunctionStore
}

When the JS engine does not find a method on the object, it looks up to the object's prototype chain (through it's __proto__) reference to the object where the method's are store. Also, this is always created implicitly in the function's environment to set context.

Let's do one more thing.

user1.hasOwnProperty('score')

I don't really see hasOwnProperty method in the userFunctionStore though. Where is this method store so that the user1 knows about it.

Object.prototype={
hasOwnProperty:function(){}
}

userFunctionStore={
increment:function(){},
login:function(){},
__proto__:Object.prototype
}

Prototypal nature of JavaScript

The new keyword automates the hard work of creating a new user object manually and returning it.

function userCreator(name,score){
this.name=name;
this.score=score;
}

userCreator.prototype.increment=function(){
this.score++
}

Interlude - Functions are both objects and functions

function multiplyBy2(num){
return num*2
}

multiplyBy2.stored=4
multuplyBy2.stored=4
multiplyBy2.prototype={}

function userCreator(name,score){
this.name=name;
this.score=score
}

userCreator.prototype.increment=function(){this.score++;)
userCreator.prototype.login=function(){console.log("Login"):

const user1=new userCreator("Eva",9);

Now I cannot look at the userCreator function and assume that it requires the new keyword to run.

Class keyword

The class keyword is just syntactic sugar.

class UserCreator(){

constructor(name,score){
this.name=name;
this.score=score
}

increment(){
this.score++
}
login(){
console.log('Login')
}

}