JavaScript 判断两个数组是否存在交集
在日常前端、全栈 JavaScript 开发中, 判断两个数组是否存在交集 是高频业务场景。常见需求包括:权限数组匹配、标签筛选、数据去重比对、列表关联校验、重复数据检测等。

很多开发者会习惯性使用双层循环或 filter + includes 实现,但不同写法的性能差距极大,尤其在处理大数组数据时,劣质写法会直接导致页面卡顿、接口响应变慢。
本文将系统性讲解 4 种主流数组交集判断方案 ,涵盖基础数组、对象数组场景,附带完整可运行 Demo 代码、原理解析、优缺点对比,同时提供获取完整交集数组的工具方法,适配所有开发场景,可直接投入项目使用。
一、场景说明
数组交集的核心定义: 两个数组中存在至少一个相同元素 。
本文所有方法均满足:只要存在一个相同元素即返回 true ,无相同元素返回 false ;同时区分「基础数据类型数组(数字、字符串)」和「引用类型对象数组」两种核心场景。
二、最优方案:Set + some(推荐生产使用)
1. 方案原理
ES6 新增的 Set 数据结构具备 O(1) 时间复杂度 的查询特性,远优于数组的 includes 、遍历查询。将其中一个数组转为 Set 存储,再遍历第二个数组,通过 Set.has() 判断元素是否存在。
搭配 Array.some() 可实现 找到匹配项立即终止遍历 ,无需遍历全部元素,性能最优,是处理大数组的首选方案,时间复杂度为 O(m+n)。
2. 完整可运行 Demo
// 判断两个基础数组是否存在交集
function hasIntersection(arr1, arr2) {
// 将第一个数组转为 Set,提升查询效率
const arrSet = new Set(arr1);
// 遍历第二个数组,找到任意一个重合元素即返回 true
return arr2.some(item => arrSet.has(item));
}
// 测试示例
console.log(hasIntersection([1, 2, 3, 4], [4, 5, 6, 7])); // true(存在交集 4)
console.log(hasIntersection([1, 2, 3], [4, 5, 6])); // false(无交集)
console.log(hasIntersection(["a", "b"], ["b", "c"])); // true(字符串交集)3. 优缺点总结
✅ 优点:性能极高、短路遍历、代码简洁、适配大数据量;
❌ 缺点:仅支持 ES6+ 环境,现代项目、小程序、浏览器均无兼容问题。
三、简易直观方案:filter + includes
1. 方案原理
通过 filter 筛选出第一个数组中存在于第二个数组的所有元素,最终判断筛选后的数组长度是否大于 0,以此判定是否存在交集。
该写法逻辑通俗易懂、代码极简,适合新手理解,适配小型数组场景。
2. 完整可运行 Demo
function hasIntersection(arr1, arr2) {
// 筛选重合元素,长度大于 0 即存在交集
return arr1.filter(item => arr2.includes(item)).length > 0;
}
// 测试示例
console.log(hasIntersection([10, 20, 30], [30, 40, 50])); // true
console.log(hasIntersection([10, 20], [30, 40])); // false3. 优缺点总结
✅ 优点:代码简单、可读性强、无需转换数据结构、零学习成本;
❌ 缺点:无法短路遍历,即使找到重合元素,仍会遍历完整个数组, 大数组性能极差 ,仅适合少量数据使用。
四、兼容兜底方案:双层 for 循环
1. 方案原理
最原始的基础算法方案,通过双层循环遍历两个数组,逐一对比元素,匹配成功后立即返回结果,实现短路终止。主要用于兼容 IE 等极低版本 JS 环境。
2. 完整可运行 Demo
function hasIntersection(arr1, arr2) {
// 双层循环遍历对比
for (let i = 0; i < arr1.length; i++) {
for (let j = 0; j < arr2.length; j++) {
if (arr1[i] === arr2[j]) {
// 匹配成功,立即返回,终止循环
return true;
}
}
}
// 遍历完成无匹配,返回 false
return false;
}
// 测试示例
console.log(hasIntersection([1, 3, 5], [2, 3, 6])); // true
console.log(hasIntersection([1, 3], [2, 4])); // false3. 优缺点总结
✅ 优点:兼容性拉满,支持所有 JS 版本,无环境限制;
❌ 缺点:时间复杂度 O(m*n),数据量稍大就会严重卡顿,现代项目 不推荐使用 。
五、进阶场景:对象数组判断交集
实际开发中,绝大多数业务数组都是 对象数组 (如用户列表、商品列表、权限列表),无法直接通过 === 或 Set 对比(对象为引用类型,地址不同则不相等)。
此时需要根据业务唯一 key(id、唯一编码、账号等)进行字段比对,以下是通用封装方案。
完整可运行 Demo
/**
* 对象数组判断是否存在交集
* @param {Array} arr1 - 第一个对象数组
* @param {Array} arr2 - 第二个对象数组
* @param {String} key - 比对的唯一字段(如 id、code)
* @returns {Boolean} 是否存在交集
*/
function hasObjIntersection(arr1, arr2, key) {
// 提取第一个数组的唯一 key,存入 Set
const keySet = new Set(arr1.map(item => item[key]));
// 比对第二个数组的 key 值
return arr2.some(item => keySet.has(item[key]));
}
// 业务测试示例
const userList1 = [{ id: 1, name: "张三" }, { id: 2, name: "李四" }];
const userList2 = [{ id: 3, name: "王五" }, { id: 2, name: "李四" }];
const userList3 = [{ id: 4, name: "赵六" }];
console.log(hasObjIntersection(userList1, userList2, "id")); // true(id=2 重合)
console.log(hasObjIntersection(userList1, userList3, "id")); // false六、拓展方法:获取两个数组的完整交集结果
除了单纯判断「是否有交集」,很多场景需要 获取所有重合的元素 ,本文封装通用工具函数,支持去重后返回纯净的交集数组。
完整可运行 Demo
// 获取两个数组的所有交集元素(自动去重)
function getIntersection(arr1, arr2) {
const set1 = new Set(arr1);
// 去重后筛选重合元素,避免重复数据
return [...new Set(arr2)].filter(item => set1.has(item));
}
// 测试示例
console.log(getIntersection([1, 2, 2, 3, 4], [3, 4, 4, 5, 6])); // [3, 4]
console.log(getIntersection(["vue", "react", "js"], ["js", "ts", "vue"])); // ["vue", "js"]七、各方案性能 & 场景选型总结
为方便项目快速选型,这里统一梳理所有方案的适用场景:
- 生产首选(通用场景) :
Set + some,性能最优、支持短路、适配大小数组; - 极简临时场景(小数据) :
filter + includes,代码简洁、快速实现; - 老旧兼容场景 :双层 for 循环,仅用于兼容极低版本浏览器;
- 业务对象数组场景 :自定义 key 比对 + Set 方案,适配 90% 业务开发;
- 需要获取交集数据 :使用封装好的
getIntersection工具函数。
八、写在最后
数组交集判断看似简单,但不同的代码写法对项目性能影响巨大。在前端大数据渲染、后端批量数据校验场景中, 拒绝双层循环、优先使用 Set 结构 是开发最优解。
本文所有代码均经过实测,可直接复制到项目中使用,覆盖了基础数组、对象数组、判断交集、获取交集全场景,是一套完整的 JavaScript 数组交集解决方案。
发布评论
评论列表 0





