我在node.js的assert
模块中遇到了一些奇怪的行为。我不确定这是一个错误还是预期的行为。
当我创建一个数组,然后在第三个元素上初始化一个值时,前两个元素是未定义的。测试前两个元素是否未定义返回true,但是将前两个元素的数组与undefined
进行比较失败。
var assert = require('assert');
var a = [];
a[2] = 2;
console.log(a); // [ , , 2 ]
assert.equal(a[0], undefined); // ok
assert.equal(a[1], undefined); // ok
assert.equal(a[2], 2); // ok
assert.deepEqual(a, [, , 2]); // ok
assert.deepEqual(a, [undefined, undefined, 2]); // error ???
我可以理解,未定义的元素与值undefined
的元素之间存在差异,因为Array
扩展Object
,而数组元素只是对象的属性。
但为什么最后一个断言失败了?
答案 0 :(得分:4)
很可能因为[,,2]
和[undefined,undefined,2]
没有相同数量的密钥:
> Object.keys([,,2]).length
1
> Object.keys([undefined,undefined,2]).length
3
以下是检查此内容的assert
代码的relevant part。
答案 1 :(得分:2)
我将在这里走出困境......
最有可能的是,deepEqual
使用对象的hasOwnProperty
方法来确保它不会捕获任何继承的属性。
如果是这种情况,以下控制台日志可能会对您有所帮助:
var test1 = [];
undefined
test1[2] = "xyzzy";
"xyzzy"
test1.hasOwnProperty(0)
false
test1.hasOwnProperty(1)
false
test1.hasOwnProperty(2)
true
var test2 = [undefined, undefined, "plugh"];
undefined
test2.hasOwnProperty(0)
true
test2.hasOwnProperty(1)
true
test2.hasOwnProperty(2)
true
答案 2 :(得分:0)
我会冒险猜测。似乎没有任何内容(即未初始化)和undefined
的数组位置之间存在区别,而实际上将undefined
实际粘贴到数组中的特定位置。
您实际上可以在控制台日志中的Chrome中看到这一点:
> a = [undefined, undefined, 2];
[undefined, undefined, 2]
> b = [,,2]
[undefined × 2, 2]
> c = [];
> c[2] = 2;
> c
[undefined × 2, 2]
这是一个非常微妙的差异;在第一种情况下([,, 2]),您在位置0
和1
中创建了一个没有任何内容的数组;它是一个备用数组,其中只有位置3
包含一个值。在第二种情况下,您创建了一个不是备用数组的数组。相反,您在undefined
和1
位置专门插入了值2
。似乎这两种情况都被区别对待,这可能是他们不平等的原因。
我认为将第一个数组可视化为[,,2] = [uninitialized, uninitialized, 2]
可能更容易。因此区别在于未初始化的值与已插入到数组中的具体 undefined 之间(这意味着该位置未被初始化)。
<强>更新强>
我在assert.js
中看了at the code。具体来说,请注意第221和222行:
if (ka.length != kb.length)
return false;
ka
和kb
在213-215行中设置:
var ka = Object.keys(a),
kb = Object.keys(b),
key, i;
Object.keys(a).length
[,,2]
的值为1
,而Object.keys(b).length
的{{1}}值为[undefined, undefined, 2]
。这就是他们不平等的原因。
答案 3 :(得分:0)
不是错误。那些数组有不同的行为。请考虑以下用例:
function log(item, idx) {
console.log(item, " - ", idx);
}
a.map(log); // 2 - 2
[undefined, undefined, 2].map(log); //undefined - 0 undefined - 0 2 - 2