【问题标题】:How to block parameters of function which is in prototype overrided after created another object如何在创建另一个对象后阻止原型中覆盖的函数的参数
【发布时间】:2020-11-22 20:09:15
【问题描述】:

为了避免复制相同的函数,我听说函数必须在prototype 中定义。而且我听说 OOP 继承很烂,这就是为什么我在深入 Javascript 时尝试使用工厂函数的原因。但是我在下面的代码中有一个问题。我在prototype 中定义了所有函数并创建了两个对象empemp2。但是在定义emp2 之后,emp 的参数会被覆盖。那么工厂函数和原型有什么好处呢?

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

【问题讨论】:

  • "我听说 OOP 继承很烂" - 你指的是哪种继承形式?他们都是面向对象的。不,如果正常使用,它们不会很糟糕。 “这就是我尝试使用工厂函数的原因” - 这样你就不再使用原型了。我的意思是,您的 createEmployee 工厂函数确实使用了原型,但是使用了错误的方式(而 eater 工厂根本没有使用原型)。为什么不直接使用简单的class 语法并尝试了解它在底层做了什么?
  • 如果你想避免复制函数(这是一个很大的 IF - 如果你喜欢这种方法完全可以),你不能在 inside 中定义任何函数或方法工厂函数。
  • 我不是指继承,我听说组合在所有情况下都有效,但类继承却不行。我对 Javascript 感到困惑,它不是类库。为什么我应该使用类语法,为什么不再响应使用类组件?
  • JavaScript 的继承实现可能不是基于类的,但这并不意味着作为抽象结构的类仍然不是一个重要的概念。 Employee 绝对是一个有实例的类。这与 React 无关。
  • 不同之处在于要共享的原型函数,不能在每次调用工厂时都重新创建。

标签: javascript prototype


【解决方案1】:

使用this 关键字而不使用new 关键字时不起作用。

"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)

带有new关键字

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)

根据这些结果:new 关键字只是使this 对象的原型引用createEmployee.prototype,就像之前的Object.create 调用一样。并返回this 对象。当使用 new 关键字调用函数或仅调用常规函数 this 时,对象会自动创建。

但我们不需要在createEmployee 工厂函数中使用this 关键字。我们只需要在我们的对象函数中使用this 关键字,例如workeat

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)

【讨论】:

    【解决方案2】:

    使用this关键字时有效

    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)
    
    
    /*
      
      //Output
     
    Muzaffer
    Muzaffer is working
    Muzaffer is eating
    after creating emp2
    Muzaffer is working
    Muzaffer is eating
    Muzaffer
      
      
      
    */
    
    

    【讨论】:

    • 如果createEmployee使用this,则必须使用new调用。如果要使用Object.create,则应使用Employee.name = nameObject.assign(Employee, {name})
    • 那个eater() 还是一团糟,没有理由有一个创建方法的函数。您应该以与work 方法完全相同的方式定义eat 方法。
    • 我尝试通过eater工厂函数进行实现组合。我知道它可以定义为 work 函数。我们可以使用this 关键字,而无需通过new 调用构造函数。那我为什么要使用new
    • 我看不到 eater 在哪里使用合成。不,你不能在工厂函数中使用this - 确保启用严格模式并看到它失败。
    • 我将eatercreateEmployee.prototype 合并,这是作文。我不再需要在工厂函数中使用this。检查我的答案。
    猜你喜欢
    • 2015-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-25
    • 1970-01-01
    • 1970-01-01
    • 2020-08-01
    • 1970-01-01
    相关资源
    最近更新 更多