当 class 包含函数时,如何比较两个 class 实例
How can I compare two class instances when the class contains functions
如果我有一个包含函数的 ES6 class,两个相同的实例不会被 chai deepEqual 考虑。在这种情况下比较实例的正确方法是什么。
例如给出这个 class 定义
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>
首先,让我们明确一点:这不是 ES6 class。那是一个 ES6(正式的,ES2015+)class加上一个class字段。 Class 字段还不是语言的一部分;当我在 2017 年 10 月写这篇文章时,他们是 Stage 3 proposal。你的
y = () => x*2;
...通过即将添加(可能)的语法向实例添加 enumerable 属性。 (和顶部附近的 x;
一样。)它应该使用 this
:
y = () => this.x*2;
// -------^^^^^
Chai 显然是在比较所有 enumerable 属性,即使它们是函数。您可以通过 Object.defineProperty
将 y
添加为 不可枚举 属性(或者,有一天,在 class 字段;现在,它们只是构造函数中的阶段 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>
如果我有一个包含函数的 ES6 class,两个相同的实例不会被 chai deepEqual 考虑。在这种情况下比较实例的正确方法是什么。
例如给出这个 class 定义
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>
首先,让我们明确一点:这不是 ES6 class。那是一个 ES6(正式的,ES2015+)class加上一个class字段。 Class 字段还不是语言的一部分;当我在 2017 年 10 月写这篇文章时,他们是 Stage 3 proposal。你的
y = () => x*2;
...通过即将添加(可能)的语法向实例添加 enumerable 属性。 (和顶部附近的 x;
一样。)它应该使用 this
:
y = () => this.x*2;
// -------^^^^^
Chai 显然是在比较所有 enumerable 属性,即使它们是函数。您可以通过 Object.defineProperty
将 y
添加为 不可枚举 属性(或者,有一天,在 class 字段;现在,它们只是构造函数中的阶段 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>