Jasmine toEqual 失败但打印两个对象相同

ps0*_*604 5 javascript jasmine jasmine2.0

在这个 Jasmine 测试中,我比较了两个几乎相同的对象,唯一的区别是第二个对象有一个额外的未定义成员。

describe('Testing', function () {

  it('should compare two objects', function () {


    var obj1 = {a: 1, b: 2 };

    var obj2 = {a: 1, b: 2, c: undefined };

    console.log(JSON.stringify(obj1));
    console.log(JSON.stringify(obj2));

    expect(obj1).toEqual(obj2);


  });
Run Code Online (Sandbox Code Playgroud)

测试失败,但是打印两个对象会JSON.stringify产生两个相同的输出。

{"a":1,"b":2}
{"a":1,"b":2}
Run Code Online (Sandbox Code Playgroud)

浏览物体可以发现差异,但在复杂的物体中这并不容易。关于如何解决这个问题有什么建议吗?

try*_*lly 1

你的问题基于两个误解:

  1. Inobj2 c是一个值为 的已定义属性undefined
  2. stringify()undefined根据规范进行序列化 - 您的测试不安全

两个对象是不平等的

茉莉花上toEqual()

toEqual使用内部函数util.equals(),它将逐个比较对象中ab中定义的所有可枚举键。

经过一些类型检查后,它开始比较对象的键

关于定义属性

查看 ECMAscript 规范。Put创建对象文字时会调用此内部方法:

11.1.5 对象初始化器

[...]

生成式 PropertyNameAndValueList : PropertyAssignment 的计算如下:

  1. 令 obj 为通过表达式 new Object() 创建新对象的结果,其中 Object 是具有该名称的标准内置构造函数。
  2. 令 propId 为计算 PropertyAssignment 的结果。
  3. 使用参数 propId.name、propId.descriptor 和false调用 obj 的 [[DefineOwnProperty]] 内部方法。
  4. 返回对象。

[...]

产生式 PropertyAssignment : PropertyName :AssignmentExpression 的计算如下:

  1. 令 propName 为计算 PropertyName 的结果。
  2. 令exprValue 为AssignmentExpression 的计算结果。
  3. 令 propValue 为 GetValue(exprValue)。
  4. 令 desc 为属性描述符{[[Value]]: propValue, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}

类似地通过成员表达式定义属性:

8.12.5 [[Put]] ( P, V, Throw ) 当使用属性 P、值 V 和布尔标志 Throw 调用 O 的 [[Put]] 内部方法时,将执行以下步骤:

[...]

  1. 否则,在对象 O 上创建一个名为 P 的命名数据属性,如下所示

    A。令 newDesc 为属性描述符 {[[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}。

    b. 调用 O 的 [[DefineOwnProperty]] 内部方法,传递 P、newDesc 和 Throw 作为参数。

的实现在8.12.9 [[DefineOwnProperty]] (P, Desc, Throw)DefineOwnProperty中描述,不再重复。MDN还表示,即使默认值也是.undefined

查看:

> var obj2 = {a: 1, b: 2, c: undefined };
> obj2.hasOwnProperty("c");
< true
Run Code Online (Sandbox Code Playgroud)

stringify()

查看JSON 规范上的ECMAscript 规范stringify()

可能的 JSON 值

(来源:json.org)

这是 ECMAscript 规范的一部分:

  1. 否则 A. 令 K 为内部字符串列表,由 [[Enumerable]] 属性为 true 的 value 的所有自身属性的名称组成。字符串的顺序应与 Object.keys 标准内置函数使用的顺序相同。

他们说,该对象的枚举属性应该符合 的顺序(和结果)Object.keys()。让我们测试一下...

> var obj2 = {a: 1, b: 2, c: undefined };
> Object.keys(obj2);
< ["a", "b", "c"]
Run Code Online (Sandbox Code Playgroud)

呃,他们是对的!

然后有一个Str()函数定义处理值的行为undefined。有几个If Type() ...步骤不适用于未定义的值,以

  1. 返回未定义

当被对象序列化器调用时:

  1. 对于 K 的每个元素 P。

    A。令 strP 为使用参数 P 和 value 调用抽象操作 Str 的结果。

    b. 如果 strP 不是未定义的

    [...]