您的问题基于两个误解:
- In
obj2
c
是一个已定义的属性,其值为undefined
。
stringify()
不undefined
根据规范进行序列化 - 您的测试不安全
两个对象不相等。
茉莉花toEqual()
toEqual使用内部的util.equals()
,它将逐个键比较对象中定义的所有可枚举键a和b。
经过某种类型检查后,它开始比较对象的键
关于定义属性
看看 ECMAscript 规范。创建对象字面量时会调用此内部Put
方法:
11.1.5 对象初始化器
[...]
产生式 PropertyNameAndValueList : PropertyAssignment 的评估如下:
- 让 obj 成为创建新对象的结果,就像通过表达式 new Object() 一样,其中 Object 是具有该名称的标准内置构造函数。
- 让 propId 是评估 PropertyAssignment 的结果。
- 使用参数 propId.name、propId.descriptor 和false调用 obj 的 [[DefineOwnProperty]] 内部方法。
- 返回对象。
[...]
产生式 PropertyAssignment : PropertyName : AssignmentExpression 的评估如下:
- 让 propName 是评估 PropertyName 的结果。
- 令 exprValue 为评估 AssignmentExpression 的结果。
- 让 propValue 为 GetValue(exprValue)。
- 设 desc 为属性描述符{[[Value]]: propValue, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}
类似地通过成员表达式定义属性:
8.12.5 [[Put]] ( P, V, Throw ) 当调用 O 的 [[Put]] 内部方法时,使用属性 P、值 V 和布尔标志 Throw,执行以下步骤:
[...]
否则,在对象 O 上创建一个名为 P 的命名数据属性,如下所示
一个。令 newDesc 为属性描述符 {[[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}。
湾。调用 O 的 [[DefineOwnProperty]] 内部方法,将 P、newDesc 和 Throw 作为参数传递。
的实现DefineOwnProperty
,在8.12.9 [[DefineOwnProperty]] (P, Desc, Throw)中描述,不再赘述。MDN 还说,即使是默认值也是undefined
.
查看:
> var obj2 = {a: 1, b: 2, c: undefined };
> obj2.hasOwnProperty("c");
< true
上stringify()
查看JSON 规范上的ECMAscriptstringify()
规范:

(来源:json.org)
这是 ECMAscript 规范的一部分:
- 否则一个。令 K 是一个内部字符串列表,由 [[Enumerable]] 属性为 true 的 value 的所有自身属性的名称组成。字符串的顺序应与 Object.keys 标准内置函数使用的顺序相同。
他们说,该对象的枚举属性应该符合Object.keys()
. 让我们测试一下...
> var obj2 = {a: 1, b: 2, c: undefined };
> Object.keys(obj2);
< ["a", "b", "c"]
嗯,他们是对的!
然后有一个Str()
函数定义了处理undefined
值的行为。有几个If Type() ...
步骤不适用于未定义的值,以
- 返回未定义。
当被对象序列化程序调用时:
对于 K 的每个元素 P。
一个。令 strP 为使用参数 P 和值调用抽象操作 Str 的结果。
湾。如果 strP 不是未定义的
[...]