两个空数组看起来不相等



我正在进行一些测试,并试图断言在对象初始化时设置了属性:

var Varity = exports.Varity = function Varity () {
this.options = extend({}, standardOptions, Varity._globalOptions);
this.expectations = [];
};

然后在我的测试中:

When -> @varity = new @subject.Varity()
Then -> expect(@varity.expectations).to.deep.equal([])

FWIW,我正在使用摩卡与摩卡给予和(希望很明显)咖啡脚本。断言库实际上是indeed(这是我写的)。我相当确信indeed的工作原理如下:

expect([]).to.deep.equal([])

和2),在构造函数的末尾和测试中,logging@varity.expectations都显示它是一个空数组。

我还在indeed的实现中放置了日志,以确保它到达正确的代码路径,并在那里记录了实际和期望。它们都以[]的身份登录。在indeed中,我使用_.isEqual进行深层对象比较。记录以下内容返回false:

_(actual).isEqual(expectation); // where actual is "@varity.expectations" and expectation is "[]"

因此,我将代码追溯到_的实现中,并开始记录日志。发现问题就在这里(在eq方法中——我刚刚搜索了isEqual,如果有人想自己查看代码的话,它是第一个命中的):

var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
_.isFunction(bCtor) && (bCtor instanceof bCtor))) {
return false;
}

记录aCtor和btor给出的结果是:

[Function: Array]

所以它们看起来是相等的,但我放在if中的日志运行,所以aCtor !== bCtor的计算结果为true!

为了彻底起见,以下DO也报告为真:

expect(@varity.expectations.join('').split('')).to.deep.equal([])
expect(@varity.expectations.toString()).to.deep.equal([].toString())
expect(JSON.stringify(@varity.expectations)).to.deep.equal(JSON.stringify([]))
expect([].slice.call(@varity.expectations)).to.deep.equal([])

但这是错误的:

expect(@varity.expectations.constructor).to.deep.equal([].constructor)

这是真的:

expect(@varity.expectations.constructor.toString()).to.deep.equal([].constructor.toString())

这是隐藏(不可枚举)属性抛出比较的情况吗?我没有在this.expectations上设置任何其他内容(实际上打印在那里的代码——Varity构造函数——是构造函数的整体)。

编辑:我猜想这个问题与咖啡脚本有关。两个相同的功能不是===:

function () {} === function () {} // false

只有当它们实际上是相同的函数时,它们才是相等的。理论上,两个Array构造函数应该是相同的函数。事实上它们不是,这让我怀疑问题出在咖啡脚本上。其中一个数组来自coffeescript,另一个来自javascript。我无法想象coffeescript没有使用默认的数组构造函数,但也许在编译时发生了某种神奇的事情?作为参考,我使用的是coffescript 1.6.1版本(并且仅用于测试)。

首先,我是对的,这不是我的indeed库的问题。我最近在should.js上观察到了同样的行为。

其次,这是一个咖啡脚本汇编的东西。类编译为表达式(而不是声明),这意味着:

class Foo

编译为

var Foo;
Foo = (function() {
function Foo() {}
return Foo;
})();

而不是

Foo = function Foo () {}

因此,Foo的构造函数是[Function: Function](闭包),而不是[Function: Foo]。数组似乎会发生类似的情况,导致javascript中生成的空数组(或对象)与coffeescript中生成的数组不同。

第三,我已经为此写了一个下划线修复程序,我在测试中使用它:

_.mixin({
fix: function(thing) {
return JSON.parse(JSON.stringify(thing));
}
});

可以这样称呼:

Then -> expect(_.fix(@varity.expectations)).to.deep.equal([])

最新更新