ES6类的优雅混合/组合语法是什么?

时间:2019-05-10 18:37:06

标签: javascript mixins prototypal-inheritance

我正在寻找一种干净简单的方法来将方法混入不同的类。我能够找到的大多数示例都使用JS prototype,例如this

示例代码:

const _ = require("underscore")

let actions = {
  speak() {
    console.log(this.name + " animal speak")
  },

  look() {
    console.log(this.name + " animal looks")
  }
}

class Dog {
  constructor(name) {
    console.log("new Dog", name)
    this.name = name

    // modify instance and return
    let that = _.extend(this, actions)
    return that
  }

  speak() {
    console.log(this.name + " dog speaks")
  }

  bark() {
    console.log(this.name + " dog barks")
  }

}

function test() {
  let rover = new Dog("rover")

  // speak in "actions" overrides Dog.speak method
  rover.speak() // => rover animal speak

  // runtime works but ts-lint doesn't like it
  // look property doesn't exist on type 'dog'
  rover.look() // => rover animal looks

  // from dog since the method doesn't exist on actions
  rover.bark() // => rover dog barks
}

test()

所以要使用原型,我可以将上面的内容修改为:

Object.assign(Dog.prototype, actions)

,然后仅使用可返回this

的普通构造函数
class Dog {

  constructor(name) {
    this.name = name
  }
...
}

Object.assign(Dog.prototype, actions)

在两种情况下,mixin speak方法都将替换Dog Class speak方法,好的。

所以我的问题是:是否还有其他更简单/更清洁的方法来混合类中的方法?

在添加原型方面,上述内容有什么问题吗?这是创建实际方法的副本吗?如果只是在原型中,而不是在每个实例中,我想都可以,但是还不能完全消除那里的任何内存问题。

1 个答案:

答案 0 :(得分:0)

除了使用mixins之外,您还可以使用extends继承继承类上的方法。

与mixins相比,继承的缺点是您一次只能扩展一个类,但是可以使用多个mixins。因此,这取决于您使用哪种用例。

这里是一个例子:

class Animal {
  constructor(name) {
    console.log("new", this.constructor.name, name)
    this.name = name

  }
  
  speak() {
    console.log(this.name + " animal speak")
  }

  look() {
    console.log(this.name + " animal looks")
  }
}

class Dog extends Animal {
  constructor(name) {
    super(name)
  }

  speak() {
    console.log(this.name + " dog speaks")
  }

  bark() {
    console.log(this.name + " dog barks")
  }

}

const dog = new Dog('Fred')
// Will call the overridden speak method on Dog
dog.speak() // Fred dog speaks
// Will call look on Animal as it hasn't been overriden in Dog
dog.look() // Fred animal looks