当类包含函数时,如何比较两个类实例

时间:2017-10-04 13:33:45

标签: javascript chai

如果我有一个包含函数的ES6类,则chai不会将两个相同的实例视为deepEqual。在这种情况下比较实例的正确方法是什么。

例如,给定此类定义

class Foo {
  x;

  constructor(x) {
    this.x = x;
  }

  y = () => x*2;
}

前两个测试通过,但第三个测试失败

describe('class equality', function() {
  it('compare single instance', function() {
    var foo = new Foo(1);
    assert.deepEqual(foo, foo);
  });

  it('compare string', function() {
    assert.deepEqual(JSON.stringify(new Foo(1)), JSON.stringify(new Foo(1)));
  });

  it('compare instance', function() {
    assert.deepEqual(new Foo(1), new Foo(1));
  });
});

在这里展示(同样on jsFiddle - 注释第12行,所有三个测试都通过:

mocha.setup('bdd');

var assert = chai.assert;

class Foo {
  x;

  constructor(x) {
    this.x = x;
  }
  
  y = () => x*2;
}
  
describe('class equality', function() {
	it('compare single instance', function() {
    var foo = new Foo(1);
    assert.deepEqual(foo, foo);
  });

	it('compare string', function() {
    assert.deepEqual(JSON.stringify(new Foo(1)), JSON.stringify(new Foo(1)));
  });

	it('compare instance', function() {
    assert.deepEqual(new Foo(1), new Foo(1));
  });
});

mocha.run();
<link href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.css" rel="stylesheet"/>

<div id="mocha"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.4.1/chai.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.js"></script>

1 个答案:

答案 0 :(得分:1)

首先,让我们明确一点:那不是ES6课程。这是ES6(正式,ES2015 +)类 类字段。类字段还不是语言的一部分;当我在2017年10月写这篇文章时,他们是Stage 3 proposal。您的

y = () => x*2;

...通过即将添加的(可能)语法向实例添加可枚举属性。 (与顶部附近的x;一样。)它应该使用this

y = () => this.x*2;
// -------^^^^^

Chai显然正在比较所有可枚举的属性,即使它们是函数。您可以通过y(或某天,在课程字段中使用decorator将您的Object.defineProperty添加为不可枚举的属性;此时,他们'在构造函数中只修改阶段2):

Object.defineProperty(this, "y", {
  value: () => this.x * 2
});

更新了代码段:

mocha.setup('bdd');

var assert = chai.assert;

class Foo {
  x;

  constructor(x) {
    this.x = x;
    Object.defineProperty(this, "y", {
      value: () => this.x * 2
    });
  }
}
  
describe('class equality', function() {
	it('compare single instance', function() {
    var foo = new Foo(1);
    assert.deepEqual(foo, foo);
  });

	it('compare string', function() {
    assert.deepEqual(JSON.stringify(new Foo(1)), JSON.stringify(new Foo(1)));
  });

	it('compare instance', function() {
    assert.deepEqual(new Foo(1), new Foo(1));
  });
});

mocha.run();

console.log(new Foo(4).y());
<link href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.css" rel="stylesheet"/>

<div id="mocha"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.4.1/chai.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.js"></script>

那就是说,y是一个非常好的候选人,而不是在原型上,这也解决了问题:

mocha.setup('bdd');

var assert = chai.assert;

class Foo {
  x;

  constructor(x) {
    this.x = x;
  }
  
  y() {
    return this.x * 2;
  }
}
  
describe('class equality', function() {
	it('compare single instance', function() {
    var foo = new Foo(1);
    assert.deepEqual(foo, foo);
  });

	it('compare string', function() {
    assert.deepEqual(JSON.stringify(new Foo(1)), JSON.stringify(new Foo(1)));
  });

	it('compare instance', function() {
    assert.deepEqual(new Foo(1), new Foo(1));
  });
});

mocha.run();
<link href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.css" rel="stylesheet"/>

<div id="mocha"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.4.1/chai.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.js"></script>