我正在编写一些代码来检查2个数组是否相同,但是由于某种原因,当期望为false时结果为true。仔细检查后发现,未定义的数组值被跳过。
const arr1 = [, , 3, 4]
const arr2 = [1, 2, 3, 4]
const result = arr1.every((item, index) => item === arr2[index])
console.log(result) // true (HOW????)
所以我花了一些时间尝试正确地获取值,但我唯一想到的是一个常规的for循环,该循环基于数组长度而不是实际项进行迭代。
为什么会发生这种情况,有没有办法识别我的数组中这些空/未定义的值?
答案 0 :(得分:12)
这是对forEach
仅访问实际存在的元素这一事实的扩展。我不知道有什么更深层的“为什么”,除了为缺少的元素调用回调没有多大意义。
您可以使用以下方法实现这些元素(如果就是世界):
Array.from
或Array.prototype.values
或Array.prototype.entries
...或其他一些人。
const a = [, , 3];
console.log(a.hasOwnProperty(0)); // false
const b = [...a];
console.log(b.hasOwnProperty(0)); // true
const c = Array.from(a);
console.log(b.hasOwnProperty(0)); // true
通过Array.from
将其应用于您的函数:
const arr1 = [, , 3, 4]
const arr2 = [1, 2, 3, 4]
const result = Array.from(arr1).every((item, index) => item === arr2[index])
console.log(result) // false
当然,这涉及到创建一个新数组并循环遍历上一个复制元素。使用自己的for
循环可能会更好。
将Array.prototype.entries
应用于您的函数:
const arr1 = [, , 3, 4]
const arr2 = [1, 2, 3, 4]
let result = true;
for (const [index, value] of arr1.entries()) {
if (value !== arr2[index]) {
result = false;
break;
}
}
console.log(result) // false
答案 1 :(得分:3)
因为语言设计是如此。 ??♂️
请参见the specification,其中指出:
- 重复,而k
- 让Pk为ToString(k)。
- 让 kPresent具有HasProperty (O,Pk)。
- ReturnIfAbrupt(kPresent)。
- 如果kPresent为true ,则
…然后进行操作。
由于从未将值分配给0
和1
属性,因此HasProperty
测试给出false
,因此If
规则将其跳过
答案 2 :(得分:1)
由.every()
的文档组成:
回调仅被调用 用于已分配值的数组索引;它不被调用 用于已删除或从未分配的索引 值。
因此,您正在使用带有array1真实值的.every()调用:
const arr1 = [, , 3, 4]
arr1.every((x, idx) => {
console.log(`element: ${x}`, `index: ${idx}`);
return true;
})
答案 3 :(得分:1)
当HasProperty为false时,内置的迭代函数(将由其他人描述并在规范中定义)将跳过值。
您可以为all
创建自己的垫片,该垫片将检查每个值。这将是原型的扩展。另外,如果将此代码用于更广泛的范围,则将其转换为函数会是更好的设计,并且需要稍有不同的调用。
const arr1 = [, , 3, 4];
const arr2 = [1, 2, 3, 4];
Array.prototype.all = function(callback){
for(let i = 0; i < this.length; i++){
if(callback(this[i],i,this)) return false;
}
return true;
};
const result2 = arr1.all((item, index) => item === arr2[index]);
console.log(result2); // false