JavaScript:为何array.includes不适配字典数组?如何解决?
问题原因与解决方案
问题原因
JavaScript里的数据类型分为值类型(如字符串、数字)和引用类型(如对象、数组),两类类型的比较逻辑完全不同:
- 值类型用
===比较时,直接对比内容是否一致; - 引用类型用
===比较时,对比的是对象在内存中的存储地址,只有两个变量指向同一个对象时,才会返回true。
array.includes()方法内部依赖严格相等运算符===做判断。当你调用coords.includes({'x': 0, 'y': 0})时,传入的是一个新创建的对象——它和数组中原有的{'x': 0, 'y': 0}虽然内容相同,但属于两个独立的内存对象,地址不一样,所以===返回false,最终includes输出false。
而字符串数组的场景中,'0-0'是值类型,两次创建的'0-0'内容一致,===返回true,所以includes能正常工作。
解决方案
1. 用array.some()自定义对象比较逻辑
some()方法可以遍历数组,自定义判断条件,适合精准对比对象属性:
var coords = [{'x': 0, 'y': 0}, {'x': 2, 'y': 5}, {'x': 1, 'y': 6}]; const target = {'x': 0, 'y': 0}; // 针对固定属性的简单对比 const exists = coords.some(item => item.x === target.x && item.y === target.y); console.log(exists); // 输出: true // 通用对象对比函数(适配多属性场景) function isEqual(objA, objB) { const keysA = Object.keys(objA); const keysB = Object.keys(objB); if (keysA.length !== keysB.length) return false; return keysA.every(key => objA[key] === objB[key]); } const existsGeneral = coords.some(item => isEqual(item, target));
2. 将对象转为值类型后使用includes
把对象序列化为JSON字符串,转成值类型后再用includes判断:
var coords = [{'x': 0, 'y': 0}, {'x': 2, 'y': 5}, {'x': 1, 'y': 6}]; const targetStr = JSON.stringify({'x': 0, 'y': 0}); // 直接遍历对比字符串 const exists = coords.some(item => JSON.stringify(item) === targetStr); // 或者先转换整个数组再判断 const strCoords = coords.map(item => JSON.stringify(item)); console.log(strCoords.includes(targetStr)); // 输出: true
⚠️ 注意:这种方式依赖对象属性的顺序,若两个对象属性顺序不同(如{'x':0,'y':0}和{'y':0,'x':0}),序列化后的字符串会不一样,导致判断错误。
3. 复用对象引用
如果能提前获取目标对象的引用,直接用includes即可:
const target = {'x': 0, 'y': 0}; var coords = [target, {'x': 2, 'y': 5}, {'x': 1, 'y': 6}]; console.log(coords.includes(target)); // 输出: true
内容的提问来源于stack exchange,提问作者Sacha Jubinville
相关产品推荐
相关产品推荐

