Search code examples
javascriptprototype

How to block parameters of function which is in prototype overrided after created another object


To avoid copies of the same function I hear that functions must define in prototype. And I hear that OOP inheritance is suck that is why I tried to use factory function when go deep in Javascript. But I have a problem in the following code. I defined all functions in prototype and create two object, emp and emp2. But after defined emp2, parameters of emp is overrided. So what is benefit of factory function and prototype?

const eater = (state) => ({
  eat(){
    console.log(state.name, 'is eating')
  }
})



function createEmployee(name, age){
  let Employee = Object.create
    (createEmployee.prototype)
  Employee.name = name 
  Employee.age = age 
  
  Object.assign(
    createEmployee.prototype, 
    eater(Employee)
  )
  
  createEmployee.prototype.work = function(){
    console.log(Employee.name, 'is working')
  } 
 
  
  return Employee
}

let emp = createEmployee('Muzaffer', 24)
emp.work()
emp.eat()
let emp2 = createEmployee('Cuma', 22)
emp.work()
emp.eat()
//Output 
//Muzaffer is working
//Muzaffer is eating
//Cuma is working
//Cuma is eating

Solution

  • It doesn't work when using this keyword without new keyword.

    "use strict";
    const eater = () => ({
      eat(){
        console.log(this.name, 'is eating')
      }
    })
    
    Object.assign(
      createEmployee.prototype, 
      eater()
    )
     
    
    function createEmployee(name, age){
        
      let Employee = Object.create(createEmployee.prototype)
       
      this.name = name 
      this.age = age 
       
      return Object.assign(Employee, this)
    }
    
    createEmployee.prototype.work = function(){
      console.log(this.name, 'is working')
    } 
    
    let emp = createEmployee('Muzaffer', 24)
    console.log(emp.name)
    emp.work()
    emp.eat()
    let emp2 = createEmployee('Cuma', 22)
    console.log('after creating emp2')
    emp.work()
    emp.eat()
    console.log(emp.name)

    With new keyword

    const eater = () => ({
      eat(){
        console.log(this.name, 'is eating')
      }
    })
    
    Object.assign(
      createEmployee.prototype, 
      eater()
    )
     
    
    function createEmployee(name, age){
      
      this.name = name 
      this.age = age 
      
    }
    createEmployee.prototype.work = function(){
      console.log(this.name, 'is working')
    } 
    
    let emp = new createEmployee('Muzaffer', 24)
    console.log(emp.name)
    emp.work()
    emp.eat()
    let emp2 = new createEmployee('Cuma', 22)
    console.log('after creating emp2')
    emp.work()
    emp.eat()
    console.log(emp.name)

    According to these result: new keyword just makes the prototype of the this object refer to createEmployee.prototype, like the Object.create call did before. And return this object. When calling a function with new keyword or just calling regular function this object create autumaticly.

    But we dont need to use this keyword in createEmployee factory function. We just need this keyword in our object function like work and eat.

    const eater = () => ({
      eat(){
        console.log(this.name, 'is eating')
      }
    })
    
    Object.assign(
      createEmployee.prototype, 
      eater()
    )
     
    
    function createEmployee(name, age){
        
      let Employee = Object.create(createEmployee.prototype)
       
      Employee.name = name 
      Employee.age = age 
       
      return Employee 
    }
    
    createEmployee.prototype.work = function(){
      console.log(this.name, 'is working')
    } 
    
    let emp = createEmployee('Muzaffer', 24)
    console.log(emp.name)
    emp.work()
    emp.eat()
    let emp2 = createEmployee('Cuma', 22)
    console.log('after creating emp2')
    emp.work()
    emp.eat()
    console.log(emp.name)