首页 文章 精选 留言 我的

精选列表

搜索[JavaScript],共9118篇文章
优秀的个人博客,低调大师

JavaScript数组去重(12种方法,史上最全)

数组去重,一般都是在面试的时候才会碰到,一般是要求手写数组去重方法的代码。如果是被提问到,数组去重的方法有哪些?你能答出其中的10种,面试官很有可能对你刮目相看。 在真实的项目中碰到的数组去重,一般都是后台去处理,很少让前端处理数组去重。虽然日常项目用到的概率比较低,但还是需要了解一下,以防面试的时候可能回被问到。 注:写的匆忙,加上这几天有点忙,还没有非常认真核对过,不过思路是没有问题,可能一些小细节出错而已。 数组去重的方法 一、利用ES6 Set去重(ES6中最常用) functionunique(arr){ returnArray.from(newSet(arr)) }vararr=[1,1,'true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN,NaN,'NaN',0,0,'a','a',{},{}];console.log(unique(arr)) //[1,"true",true,15,false,undefined,null,NaN,"NaN",0,"a",{},{}] 不考虑兼容性,这种去重的方法代码最少。这种方法还无法去掉“{}”空对象,后面的高阶方法会添加去掉重复“{}”的方法。 二、利用for嵌套for,然后splice去重(ES5中最常用) functionunique(arr){ for(vari=0;i<arr.length;i++){ for(varj=i+1;j<arr.length;j++){ if(arr[i]==arr[j]){//第一个等同于第二个,splice方法删除第二个 arr.splice(j,1); j--; } } }returnarr; }vararr=[1,1,'true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN,NaN,'NaN',0,0,'a','a',{},{}]; console.log(unique(arr)) //[1,"true",15,false,undefined,NaN,NaN,"NaN","a",{…},{…}]//NaN和{}没有去重,两个null直接消失了 双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值。 想快速学习更多常用的ES6语法,可以看我之前的文章《学习ES6笔记──工作中常用到的ES6语法》。 三、利用indexOf去重 functionunique(arr){ if(!Array.isArray(arr)){ console.log('typeerror!') return } vararray=[]; for(vari=0;i<arr.length;i++){ if(array.indexOf(arr[i])===-1){ array.push(arr[i]) } } returnarray; }vararr=[1,1,'true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN,NaN,'NaN',0,0,'a','a',{},{}];console.log(unique(arr)) //[1,"true",true,15,false,undefined,null,NaN,NaN,"NaN",0,"a",{…},{…}]//NaN、{}没有去重 新建一个空的结果数组,for循环原数组,判断结果数组是否存在当前元素,如果有相同的值则跳过,不相同则push进数组。 四、利用sort() functionunique(arr){ if(!Array.isArray(arr)){ console.log('typeerror!') return; } arr=arr.sort() vararrry=[arr[0]]; for(vari=1;i<arr.length;i++){ if(arr[i]!==arr[i-1]){ arrry.push(arr[i]); } } returnarrry; } vararr=[1,1,'true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN,NaN,'NaN',0,0,'a','a',{},{}]; console.log(unique(arr))//[0,1,15,"NaN",NaN,NaN,{…},{…},"a",false,null,true,"true",undefined]//NaN、{}没有去重 利用sort()排序方法,然后根据排序后的结果进行遍历及相邻元素比对。 五、利用对象的属性不能相同的特点进行去重(这种数组去重的方法有问题,不建议用,有待改进) functionunique(arr){ if(!Array.isArray(arr)){ console.log('typeerror!') return } vararrry=[]; varobj={}; for(vari=0;i<arr.length;i++){ if(!obj[arr[i]]){ arrry.push(arr[i]) obj[arr[i]]=1 }else{ obj[arr[i]]++ } } returnarrry; } vararr=[1,1,'true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN,NaN,'NaN',0,0,'a','a',{},{}]; console.log(unique(arr))//[1,"true",15,false,undefined,null,NaN,0,"a",{…}]//两个true直接去掉了,NaN和{}去重 六、利用includes functionunique(arr){ if(!Array.isArray(arr)){ console.log('typeerror!') return } vararray=[]; for(vari=0;i<arr.length;i++){ if(!array.includes(arr[i])){//includes检测数组是否有某个值 array.push(arr[i]); } } returnarray }vararr=[1,1,'true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN,NaN,'NaN',0,0,'a','a',{},{}]; console.log(unique(arr)) //[1,"true",true,15,false,undefined,null,NaN,"NaN",0,"a",{…},{…}]//{}没有去重 七、利用hasOwnProperty functionunique(arr){ varobj={}; returnarr.filter(function(item,index,arr){ returnobj.hasOwnProperty(typeofitem+item)?false:(obj[typeofitem+item]=true) }) } vararr=[1,1,'true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN,NaN,'NaN',0,0,'a','a',{},{}]; console.log(unique(arr))//[1,"true",true,15,false,undefined,null,NaN,"NaN",0,"a",{…}]//所有的都去重了 利用hasOwnProperty判断是否存在对象属性 八、利用filter functionunique(arr){ returnarr.filter(function(item,index,arr){ //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素 returnarr.indexOf(item,0)===index; }); } vararr=[1,1,'true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN,NaN,'NaN',0,0,'a','a',{},{}]; console.log(unique(arr))//[1,"true",true,15,false,undefined,null,"NaN",0,"a",{…},{…}] 九、利用递归去重 functionunique(arr){ vararray=arr; varlen=array.length; array.sort(function(a,b){//排序后更加方便去重 returna-b; }) functionloop(index){ if(index>=1){ if(array[index]===array[index-1]){ array.splice(index,1); } loop(index-1);//递归loop,然后数组去重 } } loop(len-1); returnarray; } vararr=[1,1,'true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN,NaN,'NaN',0,0,'a','a',{},{}]; console.log(unique(arr))//[1,"a","true",true,15,false,1,{…},null,NaN,NaN,"NaN",0,"a",{…},undefined] 十、利用Map数据结构去重 functionarrayNonRepeatfy(arr){ letmap=newMap(); letarray=newArray();//数组用于返回结果 for(leti=0;i<arr.length;i++){ if(map.has(arr[i])){//如果有该key值 map.set(arr[i],true); }else{ map.set(arr[i],false);//如果没有该key值 array.push(arr[i]); } } returnarray; } vararr=[1,1,'true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN,NaN,'NaN',0,0,'a','a',{},{}]; console.log(unique(arr))//[1,"a","true",true,15,false,1,{…},null,NaN,NaN,"NaN",0,"a",{…},undefined] 创建一个空Map数据结构,遍历需要去重的数组,把数组的每一个元素作为key存到Map中。由于Map中不会出现相同的key值,所以最终得到的就是去重后的结果。 十一、利用reduce+includes functionunique(arr){ returnarr.reduce((prev,cur)=>prev.includes(cur)?prev:[...prev,cur],[]); } vararr=[1,1,'true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN,NaN,'NaN',0,0,'a','a',{},{}];console.log(unique(arr));//[1,"true",true,15,false,undefined,null,NaN,"NaN",0,"a",{…},{…}] 十二、[…new Set(arr)] [...newSet(arr)]//代码就是这么少----(其实,严格来说并不算是一种,相对于第一种方法来说只是简化了代码) PS:有些文章提到了foreach+indexOf数组去重的方法,个人觉得都是大同小异,所以没有写上去。 原文发布时间为:2018-10-15 本文作者:沉静地闪光 本文来自云栖社区合作伙伴“编程微刊”,了解相关信息可以关注“编程微刊”。

优秀的个人博客,低调大师

JavaScript—call, apply, bind 函数能干啥?(全)(20)

call(),apply(),bind() 函数大家可能都有所了解,但是在平时搬砖过程中很可能或者基本没用过,学过但都淡忘了。 但是在大量第三方的框架(库),甚至js自己都在 源码中大量使用 call,apply 函数。所以今天和大家仔细讨论下它们在 开发中的应用场景 。 1 . 它们是啥意思1.1 作用他们的作用都是改变函数内部的this。这三个函数都是函数对象的方法,也就是说只有函数才可以直接调用这些方法。1.2 三者区别参数: 三个函数的第一个参数都是需要绑定的 this。call: 可以有n个参数,从第二个参数开始的所有参数都是原函数的参数。 `apply`:只有两个参数,并且第二个参数必须为数组,数组中的所有元素一一对应原函数的参数。 `bind`: 只有一个参数,即要绑定的this。 call 语法: foo.call(this, arg1,arg2, ... ,argn ); apply 语法: foo.apply(this, [ arg1,arg2, ... ,argn ] ); bind 语法: foo.bind(this); 调用:call,apply: 调用后立即执行原函数。 `bind`: 调用后返回已经绑定好this的函数。 小例子一枚: function foo(a,b){ console.log(a+b); } foo.call(null,'海洋','饼干'); // 海洋饼干 这里this指向不重要就写null了 foo.apply(null, ['海洋','饼干'] ); // 海洋饼干 var fun = foo.bind(null); fun('海洋','饼干'); // 海洋饼干 2 .它们能干啥事这是我们今天讨论的主题,这三个函数如何应用?什么情况下使用?能改变this指向又能咋滴? 2 .1 处理伪数组 (最常用)先考虑一个问题,如果你使用var arr = document.getElementsByTagName('li')获取了5个li元素,你现在需要获取其中的第2,3,4三个元素,你会怎么做? 这样arr.slice(1,4);? 啊哦,TypeError -- arr.slice is not a function(slice不是函数),数组操作在日常搬砖中非常常见,我见过最傻的解决这个问题的方式是使用循环,将需要的元素一个个添加到一个新数组里0.0,下面我介绍的方法完全可以在实战中使用,可以给你的代码加分哦,非常方便简洁(中高级前端程序员中,算是基本操作了)。 先要介绍一个概念( 伪数组 ),这也是为什么我们刚刚slice切割数组时出错的原因: (对新手来说算是干货了,知道的可以跳过) 什么是伪数组?( 字面的意思已经呼之欲出了 ) 有length属性能按索引存储数据能像遍历数组一样来遍历不能使用数组的push()、slice()等方法简单来说就是可以像数组一样操作的对象,但是没有数组的方法。 js中存在大量伪数组,如 : 1. function的arguments对象。 2. getElementsByName(),getElementsByTagName(),childNodes/children 等方法的返回值。 3. 还有比较常见的jquery,使用它获取的元素也是伪数组。 回到原来的问题,如何截取伪数组中的元素:伪数组没有这些方法,我们'借用'Array的slice不就行了 [].slice.call(arr,1,4); // 推荐写法 不想借用你可以直接给伪数组添加一个slice函数,如 arr.slice = [].slice; arr.slice(1,4); 当然,'借用' 更方便,直接添加会导致伪数组对象'污染'。 如果可以随意改变原对象,可以 直接将其转成真正的数组对象。 [].slice.call(arr); 2 .2 继承继承方式多种多样,我们现在讨论的这种是其中很重要的一种实现方式,用call实现 js 构造函数继承 。 单继承 function person(name){ this.name = name } function man(name){ this.age = '男'; person.call(this,name); // 继承 man } var me = new man('海洋饼干'); console.log(me.name,me.age); // '海洋饼干' '男' 多继承 function person(name){ this.name = name } function man(name){ this.age = '男'; } function manProgrammer(name){ this.girlfriend = null; person.call(this,name); // 继承 person man.call(this,name); // 继承 man } var me = new manProgrammer('海洋饼干'); console.log(me.name,me.age,me.girlfriend); // '海洋饼干' '男' null 2 .3 this 硬绑定 --- bind将一个对象强制且永久性绑定到函数的this上,使用call,apply或者其他的绑定方式都无法改变(除了new绑定,当然,可以手动撸一个new都无法改变的硬绑定) 直接看例子: var fun ; var obj = { a : 1, foo : function(){ var _this = this; //平时有没有过这种写法? 为了防止this指向问题 //将this赋值给一个变量,间接维持了this的安全性 fun = function(){ console.log(_this.a); } } } obj.foo(); fun(); // 1 var obj1 = { a : 2} obj.foo.call(obj1); // 直接修改_this所绑定的值,boom了 fun(); // 2 但是这种方法感觉上是在逃避问题,直接不使用this了 ? 这真的不是什么好的解决问题的态度。下面使用我们的bind来优化一下: var fun ; var obj = { a : 1, foo : function(){ // 不使用 _this, 避免无谓的变量声明 fun = function(){ console.log(this.a); }.bind(this); // 代码很简洁,很漂亮(b格) } } var obj1 = { a : 2} obj.foo(); fun(); // 1 fun.call(obj1); // 1 call ,apply等绑定 无法修改 // 这里和上面call的位置不同是因为this所处于不同的位置 这样替代 _this 很规(zhuang)范(b)呢 2 .4 取数组最大最小值Math.max和min方法,接收多个参数,比较出极值,这里用到apply的一个默认功能:展开数组,传入一个数组参数就可以默认将这个数组转成一个个参数的形式赋给原函数 var num = [6,9,-3,-5]; console.log(Math.max.apply(Math,num)); // 9 等价 console.log(Math.max(6,9,-3,-5)); console.log(Math.min.apply(Math,num)); // -5 等价 console.log(Math.min(6,9,-3,-5)); 2 .5 合并数组合并数组常见有三种方式,1.循环 2.Array的concat() 3. 使用apply()合并 这里是使用最简便的apply var a = [1,2,3]; var b = [4,5,6]; [].push.apply(a,b); // 借用数组的push方法 等价 a.push(4,5,6); console.log(a); // [1, 2, 3, 4, 5, 6]

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册