JS中的indexOf与Set(其实是引用类型比较的问题)

起因是想在一个二维数组中查找是否包含一个一维数组

indexOf

先看个例子:

const arr = [[1, 1], [2, 2]]
if(arr.indexOf([1, 1]) === -1){
    console.log("无法查到该数组") 
}else{
    console.log("已找到")
}

const arr2 = [1,2,3,4,5]
if(arr2.indexOf(2) === -1){
    console.log("无法查到该值")
}else{
    console.log("已找到")
}

// 输出
//无法查到该数组
//已找到

为啥2在一维数组中能找到,而[1,1]在原二维数组中中找不到?

其实不是indexOf的问题,而是因为js比较number, string, boolean的时候,比较的是数值,而比较数组或对象时,比较的是他们的引用

引用就是js给这个数组在内存中分配的地址,arr中的[1,1]和被拿来查找的[1,1]内存地址是不同的,所以indexOf自然会返回-1.

这是个更简单的例子:

const arr1 = [1,1]
const arr2 = [1,1]
console.log(arr1 === arr2) // false
console.log(arr1 == arr2) // false

如果想要比较两个数组中的每一个下标的数值都是否相同,可以用下面的方法

/* 如果要比较一个一维数组A与二维数组B的某一个元素B[i]值相等 */
// 方法一 逐一比较A与B[i]的值
const fatherArr = [[1, 1], [2, 2], [3, 3]];
const sonArr = [1, 1];

const containsTarget = fatherArr.some(subArray => 
    subArray.length === sonArr.length && 
    subArray.every((value, index) => value === sonArr[index])
);

if (containsTarget) {
    console.log("已找到");
} else {
    console.log("无法查到该数组");
}

//方法二 JSON.stringfy()
const containsTarget2 = fatherArr.some(subArr => JSON.stringify(subArr) === JSON.stringify(sonArr))

if (containsTarget2) {
    console.log("已找到");
} else {
    console.log("无法查到该数组");
}

Set()

来看看set中的问题,类似

const set = new Set()
set.add([1, 2])
set.add([1, 3])

console.log(set.has([1, 2])) //false 同理,比较的是两个数组的引用

解决办法:

// 如果要向set中存储数组可以先转换为字符串
const set2 = new Set()
set2.add(JSON.stringify([1, 2]))
set2.add(JSON.stringify([1, 3]))
set2.add(JSON.stringify([1, 2]))

console.log(set2.has(JSON.stringify([1, 2]))) // true

我有个习惯,每次调试js程序看看数组和对象的值都用JSON.stringify

但是看一下JSON.stringify一个Set会发生什么

const set = new Set()
set.add([1, 2])
set.add([1, 3])

console.log(JSON.stringify(set)) // {} 

为啥是{}? 因为JSON.stringify只会序列化对象的可枚举属性,set是集合,它是一种特殊的对象,没有传统对象的属性,因此会输出{}

所以要查看set的值可以用Array.from转换为数组

const set = new Set()
set.add([1, 2])
set.add([1, 3])

console.log(set.has([1, 2])) //false 
console.log(JSON.stringify(Array.from(set))) // 正确做法

并且值相同的两个set直接比较也是false,和数组的原因相同 

const set1 = new Set([1,1])
const set2 = new Set([1,1])
console.log(set1 === set2) // false
console.log(set1 == set2) // false

总结

基本数据类型(Number、String、BigInt、Boolean)会直接拿数值相互比较,引用数据类型(Object(Array\Set\Map都是特殊的Object)) 比较的是它们内存中分配的地址.

特殊情况:

const sym1 = Symbol('description');
const sym2 = Symbol('description');

console.log(sym1 === sym2); // false 
//虽然Symbol是基本数据类型 但它表示每个Symbol都是唯一 
//不是简单的字符串 没有两个Symbol是完全相等的


// 还有老生常谈的null与undefined
console.log(null == undefined); // true
console.log(null === undefined); // false

来自一个笔试踩了大坑的渣渣TT

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值