JavaScript 数组去重全解:6 种核心方法

目录

  • 核心基础知识点
  • [6 种数组去重方法详解](#6 种数组去重方法详解)
    • [方法 1:双重循环去重(基础实现)](#方法 1:双重循环去重(基础实现))
    • [方法 2:indexOf 单循环去重](#方法 2:indexOf 单循环去重)
    • [方法 3:filter + indexOf 去重](#方法 3:filter + indexOf 去重)
    • [方法 4:排序 + 相邻对比去重](#方法 4:排序 + 相邻对比去重)
    • [方法 5:对象字面量去重(空间换时间)](#方法 5:对象字面量去重(空间换时间))
    • [方法 6:ES6 Set 去重(最优简洁版)](#方法 6:ES6 Set 去重(最优简洁版))
  • 方法对比
  • 总结

核心基础知识点

题目场景

  • 需求:对数组 1,2,3,2,5,5,6,3 实现去重,得到无重复元素的新数组

代码规范与设计原则

  1. 注释规范
    注释是代码的核心组成部分,提升可读性,方便团队协作、个人回顾代码
  2. 单一职责
    一个函数只实现一个核心功能(数组去重)。
  3. 封装思想
    将复杂的去重逻辑封装为独立函数,复用性更强。
  4. 健壮性要求
    必须做参数校验,避免非数组参数导致程序报错。

必备数组 API

API 作用
Array.isArray(arr) 判断数据是否为数组(参数校验核心方法),是返回true,不是返回false
arr.indexOf(item) 查询元素在数组中第一次出现的下标,不存在返回 -1
arr.filter(callback) 数组过滤,根据回调返回值保留 / 剔除元素
arr.sort() 数组排序,为相邻去重做准备

复杂度

时间复杂度:

O(n²):双重for计数循环、filter+indexOf(效率较低)

O(nlogn):先排序再去重(中等效率)

O(n):对象 / Set 去重(最优效率,但是最消耗空间)

空间换时间:用额外对象 / Set 存储数据,提升执行速度

6 种数组去重方法详解

方法 1:双重循环去重(基础实现)

核心思路

定义结果数组,外层遍历原数组,内层遍历结果数组,通过标记判断元素是否重复,无重复则加入结果数组。

javascript 复制代码
function unique(arr){
    // 参数校验:非数组返回空数组
    if(!Array.isArray(arr)){
        console.log('type error');
        return [];
    }
    // 初始化结果数组,放入第一个元素
    let res=[arr[0]];
    // 外层循环:从第二个元素开始遍历原数组
    for(let i=1;i<arr.length;i++){
        let flag=true; // 标记:默认当前元素不重复
        // 内层循环:遍历结果数组,对比是否重复
        for(let j=0;j<res.length;j++){
            if(arr[i] === res[j]){
                flag=false; // 发现重复,修改标记
                break; // 终止内层循环
            }
        }
        // 无重复则添加到结果数组
        if(flag){
            res.push(arr[i]);
        }
    }
    return res;
}
console.log(unique([1,2,3,2,5])); // [1,2,3,5]

复杂度:O(n²)


方法 2:indexOf 单循环去重

核心思路

利用 indexOf 判断元素是否已存在于结果数组,不存在则添加,简化内层循环。

javascript 复制代码
function unique(arr){
    // 参数校验
    if(!Array.isArray(arr)){
        console.log('type error');
        return [];
    }
    const res=[];
    // 遍历原数组
    for(let i=0;i<arr.length;i++){
        // indexOf返回-1:元素不存在于结果数组
        if(res.indexOf(arr[i])===-1){
            res.push(arr[i]);
        }
    }
    return res;
}

复杂度 :O(n²)

优点:比双重循环代码更简洁


方法 3:filter + indexOf 去重

核心思路

利用 filter 过滤数组,保留第一次出现的元素 :indexOf 返回元素首次出现的下标,与当前下标一致则保留

javascript 复制代码
function unique(arr){
    // 参数校验
    if(!Array.isArray(arr)){
        console.log('type error');
        return [];
    }
    // filter:返回符合条件的新数组
    return arr.filter(function(item,index){
        // 仅保留元素第一次出现的位置
        return arr.indexOf(item)===index;
    })
}

复杂度:O(n²)

优点:代码极简,一行实现核心逻辑


方法 4:排序 + 相邻对比去重

核心思路

先对数组排序 ,重复元素会变为相邻元素,遍历数组,仅保留与前一个元素不同的值

javascript 复制代码
function unique(arr){
    // 参数校验
    if(!Array.isArray(arr)){
        console.log('type error');
        return [];
    }
    arr.sort(); // 数组排序
    let res=[arr[0]];
    // 遍历数组,对比相邻元素
    for(let i=1;i<arr.length;i++){
        if(arr[i]!==arr[i-1]){
            res.push(arr[i]);
        }
    }
    return res;
}

复杂度:O(nlogn)

注意:排序会改变原数组元素的顺序


方法 5:对象字面量去重(空间换时间)

核心思路

对象中的key表示值,value 表示它是否出现

用对象存储已出现的元素,遍历数组时,通过对象 key 判断是否重复,仅遍历一次数组,效率极高

javascript 复制代码
function unique(arr){
    // 参数校验
    if(!Array.isArray(arr)){
        console.log('type error');
        return [];
    }
    let res=[];
    let obj={}; // 对象:key存储数组元素,value标记是否存在
    for(let i=0;i<arr.length;i++){
        // 对象中无该key:表示未重复
        if(!obj[arr[i]]){
            res.push(arr[i]);
            obj[arr[i]]=1; // 标记为已存在
        }
    }
    return res;
}

复杂度:O(n)

优点:执行速度最快,大数据量优先使用


方法 6:ES6 Set 去重(最优简洁版)

核心思路

Set 是 ES6 提供的不重复数据容器,直接将数组转为 Set 去重,再展开为新数组。

javascript 复制代码
function unique(arr){
    // 参数校验
    if(!Array.isArray(arr)){
        console.log('type error');
        return [];
    }
    // 数组转Set去重 → 展开运算符转回数组
    return [...new Set(arr)];
}

复杂度:O(n)

优点:代码最简洁、性能最优、企业开发首选

方法对比

方法 复杂度 代码量 适用场景
双重循环 O(n²) 学习基础逻辑
indexOf 循环 O(n²) 中等 简单业务场景
filter+indexOf O(n²) 极简 代码简洁优先
排序 + 相邻 O(nlogn) 中等 允许改变元素顺序
对象去重 O(n) 中等 大数据量、高性能要求
ES6 Set O(n) 极简 现代浏览器 / 项目首选

总结

数组去重是前端必备基础能力,核心是判断元素是否重复;

所有方案都必须包含参数校验,保证代码健壮性;

复杂度从低到高:O(n) < O(nlogn) < O(n²);

最优方案:ES6 Set 去重,兼顾简洁性与性能;

核心思想:循环对比、API 复用、空间换时间。

相关推荐
SEO_juper1 小时前
JavaScript 渲染:AI 智能体无法读取,直接影响收录
开发语言·前端·javascript·aigc·seo·跨境电商·geo
whuhewei1 小时前
一道React缓存的题目
javascript·react.js
何何____1 小时前
js的数据存储机制
开发语言·前端·javascript·ecmascript
云水一下2 小时前
JavaScript 从零基础到精通系列:对象、数组与 ES6 数据操作利器
前端·javascript
无聊的老谢2 小时前
Vue 3 + Leaflet 实现高性能 Web GIS 基站监控平台
前端·javascript·vue.js
之歆2 小时前
Day23_Bootstrap 前端框架完全指南:从栅格系统到组件化开发
开发语言·前端·javascript·前端框架·bootstrap·ecmascript·less
前端 贾公子2 小时前
3.响应式系统基础:从发布订阅模式的角度理解 Vue2 的数据响应式原理(上)
前端·javascript·vue.js
GISer_Jing11 小时前
Three.js着色器编译机制深度解析
javascript·webgl·着色器
丷丩11 小时前
MapLibre GL JS第22课:查看本地GeoJSON
前端·javascript·map·mapbox·maplibre gl js