ES 6 JS的类继承问题及其测试失败

时间:2019-02-22 16:07:53

标签: javascript inheritance es6-class

我是来自Ruby背景的新开发人员。最近,我在JS方面一直非常努力,在新的ES 6中存在类继承方面的问题。我觉得这可能是我对JS的理解或将其与Ruby的大部分融合所致。我一直在尝试将Ruby Project转换为JS进行练习,但现在功能测试失败了。

Failing Feature test when trying to initialize two instances of a class

const STATS = { str:1, dex:1, int:1 }

class Example {
  constructor(race, clas) {
    this.race = race,
    this.clas = clas,
    this.stats = this.add(STATS)
  }
  
  add(stats) {
    if(this.race != 'empty'){
      stats.str += this.race.str
      stats.dex += this.race.dex
      stats.int += this.race.int
    }
    if(this.clas != 'empty') {
      stats.str += this.clas.str
      stats.dex += this.clas.dex
      stats.int += this.clas.int
    } 
    return stats
  }
}

var a = new Example({str: 1, dex:0, int:0}, 'empty');
var b = new Example('empty', {str: 0, dex:0, int:1});

console.log('Should be str:2 dex:1 int:1');
console.log(a.stats); 
console.log('Should be str:1 dex:1 int:2');
console.log(b.stats);

我的类具有一些在构造时会改变状态的函数,但是问题是在调用新类时,它保留了先前变量的更改。在我的功能测试中,这只是一个问题,因为这是唯一一次两次调用类。

这是我的功能测试https://github.com/RyanWolfen7/jsRPG/blob/master/cypress/integration/featureTest/characterFeature_test.js

的链接

这是未通过测试的类 https://github.com/RyanWolfen7/jsRPG/blob/master/models/characters/character.js

老实说,我可能会取消项目并重新开始,但是我想了解我的问题是什么。我对JS采用OOD方法,并将红宝石项目https://github.com/RyanWolfen7/ruby_rpg转换为JS。我不确定是因为我写的测试错误还是对es-6的工作方式有误解。

我尝试过的事情:

创建一个新对象

将新创建的对象分配给新类

1 个答案:

答案 0 :(得分:0)

这不是继承问题。实际上,它与OO无关。您看到的是以下事实的结果:javascript中的大多数东西都是引用(指针),但是您正在编写代码,好像STATS是一个值。

在您的函数add中,您需要执行以下操作:

add(stats) {
  if(this.race != 'empty'){
    // modifying passed in object, not creating new object
    stats.str += this.race.str
    stats.dex += this.race.dex
    stats.int += this.race.int
  }
  if(this.clas != 'empty') {
    // modifying passed in object, not creating new object
    stats.str += this.clas.str
    stats.dex += this.clas.dex
    stats.int += this.clas.int
  } 
  return stats
}

因此,无论您调用add()的次数是多少,无论您从Example的哪个实例调用它,您都只能访问和覆盖单个共享的STATS对象。

要在每个函数调用上创建STATS的新副本,您需要将其复制到新对象。最快的老式方法是将对象序列化为字符串,然后将字符串转换回对象:

add (input) {
  var stats = JSON.parse(JSON.stringify(input));

  // ...
}

这很难看,但是多个基准测试确实表明这是最快的方法。

现代javascript可以使用Object.assign来做到这一点:

add (input) {
  var stats = Object.assign({},input);

  // ...
}

但是,我不知道它是否更快。您必须自己对其进行基准测试。您可以对短语“ js克隆对象” 进行谷歌搜索,以获得更多信息。