2020-07-12

## 大前端基础之JS数组API及方法重构;

**一、在JS中什么叫数组:**

      数组是值的有序集合,每个值叫做一个**元素**,而每个元素在数组中有一个位置,以数字表示,称为**索引**,从0开始。js的数组是无类型的,数组元素可以是任意类型,同一个数组中的不同元素可能是对象或数组。数组元素的索引不一定要连续,元素之间可以有空隙,叫做稀疏数组 。每个数组都具有一个**length属性**。针对非稀疏数组,length属性就是数组元素的个数,针对稀疏数组,元素的length属性比所有元素的索引要大。

**二、数组的构建方式**

1)、字面量的创建;var arr=[ ];

2)、构造函数创建;var arr=new  Array();

如果通过这个方式创建函数,参数仅有一个时,且这个参数是正整数的时候,不能是负数或者小数,则表示创建一个具备该正整数长度的数组,里面有这个长度若干个空元素,如果不是数值,这个数据就会作为该数组的第零个元素,长度为1

**三、JS数组的特点;**

1)arr.length  数组的长度,元素的个数,长度可被修改,最大下标为长度减1,仅记录下标的个数,不包含属性的数量

2)arr[arr.length]=20,在数组最尾部添加一个元素

3)在对象中属性名填入任何内容都会隐式转换成字符,在数组中所有的下标都会隐式转换成number(NaN),不能转换的就会默认添加为数组的属性名

4)数组不可以用点语法获取下标变量,但是可以用点语法获取属性

**四:数组的API;总的来说数组的API有以下几个,那下面小编就介绍几种在JS中经常用到的API和数组方法重构(其中arr参数表示为数组,item参数表示为元素,index为索引);

push()+pop(), shift()+unshift(), forEach(), map(), some(), every(), filter(), reduce()+reduceRight(), indexOf()+lastIndexOf(),join(), sort(), slice(), splice(), concat(), reverse(), Array.form(), Array.of(), find()+findIndex(), entries()+keys()+values(), includes()**

**四.1;push,unshift,pop,shift**

1)push;在数组尾部添加一个或者多个元素,并且返回新数组的长度

重构push;(暂时增加一个元素)

function  pushs(arr,item){

    arr[arr.length]=item;//直接将元素添加在数组的最后

    return arr.length;//返回新数组的长度

}

2)unshift:在数组的头部增加一个或者多个元素,并且返回新数组的长度

重构unshiet;(暂时只添加一个)

function  unshift(arr,item){

    for(i=0;i<arr.length;i++){

        arr[i+1]=arr[i];//将数组元素往后移

    }

    arr[0=item]

    return arr.length//返回新数组的长度

}

3)pop;  删除数组最后一个元素,并且返回被删除的数值

重构pop;

function pops(arr,item){

    item=arr[arr.length-1];//将数组最后一个元素保存

    arr.length--

    return item//返回被删除的元素

}

4)shift; 删除头部第一个元素,并且返回被删除的元素

重构shift;

function shift(arr,item){

    item=arr[arr.length-1]//保存数组第一个元素

    for(i=0;i<arr.length,i++);

    arr[i]=arr[i+1];//将数组元素都往前移一位

    return item;//返回被删除的长度

}

eg:

var arr=[1,2,3,4,5];

        var arr1=arr.push("s",6);

        var arr2=arr.unshift("a",10);

        var arr3=arr.pop();

        var arr4=arr.shift();

        console.log(arr1,arr2,arr3,arr4);//7 9  6 "a"//在这里,arr1和arr2返回新数组的长度,arr3和arr4返回被删除的元素

**四.2;concat和join  数组的合并**

1)concat。返回一个新数组,原来的数组不变化

var arr=arr1.concat(arr2,0,["a","b"],-1);

如果直接使用,相当于复制 arr1=arr.concat;

重构concat;

function concats(arr,arr1,arr2,item){

    arr=[];//为返回新数组做准备

    for(i=0;i<arr1.length;i++){

        arr[i]=arr1[i];

    }

    for(j=0;j<arr2.length;j++){

        arr[arr1.length+j]=arr2[j];

    }//遍历数组arr1和arr2.

    arr[arr1.length+arr2.length]=item;//在已经将数组添加形成的arr数组,在其后面再拼接元素

    return arr;//返回拼接形成的新数组

}

2)join;返回指定的字符连接形成的新字符串;

如;arr=[1,2,3,4,5]

var str=arr.join("|"),默认为逗号  1|2|3|4|5;

重构join;

function joins(arr,item){

    str="";//为返回新字符串做准备

    if(item===undefined) item=","//用户未加item时,默认为逗号

    for(i=0;i<arr.length;i++){

        if(arr[i]===arr[arr.length-1]){

            str+=toString(arr[i]);//将数组最后一个元素的连接符号去掉

        }else{

            str+=toString(arr[i])+"item"'//将数组元素转化为字符串

        }

    }

    return str;//返回新字符串

}

**四.3 splice;插入,删除,替换,返回被删除的元素组成的新数组;**

arr.splice(从什么位置开始 可为负值表示由后向前,删除几个,替换的元素(一个或者多个))

重构splice方法

      //arr 为数组参数,index为索引(可以为负),arrNum为要删除的元素个数,后面可以跟需要添加的新元素。

      function splices(arr, index, arrNum) {

        //获取需要添加的元素个数(如果有的话)

        var arrArgumentsNum = arguments.length - 3;

        //设置delArr,用于以数组形式返回被删除的元素

        var delArr = [];

        //简单的判断,防止函数调用失败

        if (arr.length <= index) return 0;

        if (arrNum < 0) return 0;

        if (~index+ 1 > arr.length) return 0;

        //如果索引为负,在这里转为正(从后往前)

        if (index< 0) {

          index= index+ arr.length;

        }

        //for循环遍历删除元素,后面的元素前移

        for (i = 0; i < arr.length - index; i++) {

          if (i < arrNum) delArr[i] = arr[index+ i];

          arr[index+ i] = arr[index+ arrNum + i];

        }

        //删除多余元素

        arr.length -= arrNum;

        //如果需要插入元素,则进行下面操作

        if (arguments[3]) {

          arr.length += arrArgumentsNum;

          //循环让元素后移

          for (i = 0; i < arrArgumentsNum; i++) {

            arr[arr.length - i - 1] = arr[arr.length - arrArgumentsNum - i - 1];

          }

          //添加对应元素

          for (i = 0; i < arrArgumentsNum; i++) {

            arr[index+ i] = arguments[i + 3];

          }

        }

        return delArr;

      }

利用splice去重

Array.prototype.distinct=function(){

    for(var i=0;i<this.length;i++) {

        if(this.indexOf(this[i])!=i){

            this.splice(i,1);

            i--;

        }

    }

    return this;

}

var arr=[1,1,2,3,4,5,6,2,3,4,5,6,7,1,2,3,4,5,6];

arr.distinct();//arr=[1, 2, 3, 4, 5, 6, 7]

**四.4  slice;按指定位置截取复制内容,只能从前向后截取,第二个参数可以不写,默认到尾部;包括开始的位置,不包括结束的位置**

arr.slice(从第几位开始(可以为负数,但是必须大于后面),到第几位结束)

重构slice

function slice1(array,start,end){

            var arr1=[];

            if(!array || !Array.isArray(array)) return arr1;

            if(end===undefined)    end=array.length;

            if(start =.= undefined)  start=0;//防止用户都没有填,返回默认值

            start=Number(start);

            end=Number(end);

            if(isNaN(start))  start=0;

            if(isNaN(end))    end=array.length;

            if(start<0)      start=array.length+start;

            if(end<0)      end=array.length+end;//当为负值时,从数组后面开始算

            for(var i=start;i<end;i++){

                arr1.push(array[i]);//将选中的元素添加到新数组里

            }

            return arr1;  //返回新数组

        }

slice的应用  复制

var arr=[1,2,3];

var copies = arr.slice(0);

arr.length=0;//arr数组删除所有元素

console.log(copies);

console.log(arr);

**四.5 indexOf和lastindexOf;查找

find 返回数组中第一个符合条件的元素,findIndex返回索引(两中比较少用)**

1)indexOf(查询元素,从什么位置开始),如果查到,返回该元素的下标。并且不会在继续查找。如果没有查到,则返回-1

当查询中有数组或者对象的时候,因为引用地址不同。所以无法查到

2)lastindexOf,和indexOf一样,只不过是从数组后面开始查找

**四.6  Array.from  将类数组转换成数组,拥有数组的方法

Array.of  把参数合并成一个数组返回,如果参数为空,则返回一个空数组**

ES6中;arr=Array.from(类数组);

ES5中;arr=Array.prototepy.slice.call(类数组)

**四.7数组的遍历;**

forEach和map,for循环,for in

1)forEach  遍历数组,没有返回值

arr.forEach(function(item,index,arr){});

重构forEach

function forEach1(array,fn){

if(!array || !Array.isArray(array)) console.error("forEach1 is not function");

for(var i=0;i<array.length;i++){

fn(array[i],i,array)};

// 遍历传入的数组,把数组的元素、下标、数组传入回调函数 } //不返回任何东西 }

2)map 遍历数组,返回和原数组长度相同的新数组,如果没有定义,直接为返回元素为undefined

arr.map(function(item,index,arr){});

map的重组

function map1(array,fn){

            if(!array || !Array.isArray(array))  console.error("forEach1 is not  function");

            var arr1=[];

            for(var i=0;i<array.length;i++){

                if(array[i]===undefined)  continue;  //遍历过程中遇到undefined,跳出去这一次循环,后面继续,所以用continue;

                arr1[i]=fn(array[i],i,array);//新数组的元素是回调函数中返回的结果            }

            for(var j=0;j<arr1.length;j++){

                return  arr1[j]===undefined? undefined : arr1; 

            }  //如果新数组元素之undefined,返回undefined,如果不是,返回新数组          }

3)for in 遍历数组,index为下标,arr[index]为属性值  for(index in arr){}

以上方法会跳过空元素;

4) for循环  for(i=0;i<arr.length;i++){}

**四.8排序;(空间复杂度和事件复杂度)  sort

在排序时,sort()方法会调用每个数组项的 toString()转型方法,然后比较得到的字符串,以确定如何排序。即使数组中的每一项都是数值, sort()方法比较的也是字符串**

1)冒泡排序;

function sorts(arr,item){

    for(i=0;i<arr.length-1;i++){

        for(j=0;j<arr.length-1-i;j++){

        if(arr[j]>arr[j+1]){

            item=arr[j];

            arr[j]=arr[j+1];

            arr[j+1]=item;

            }

        }

    }

}

2)str.charCodeAt()将字符串的第0项转换成Unicode编码

如;var str="cbd012" 长度为6,从为第0项;

str.charCodeAt(0);//将字符串的第0项转化为Unicode编码

3)Math.random()-0.5;将数组随机乱序

4)数组的排序方式  sort  只适用于数组

arr.sort(function(后一项(a),前一项(b))){

    return a-b //从小到大

    return b-a //从大到小

}

**四.9 some和every**

1)some 查找数组是否有满足条件的元素,如果有就是返回true,不继续向后遍历,没有返回false

arr.some(function(item,index,arr){})

重构some

function somes(arr,fn){

    if(fn){

        return true

    }else{

        return false

    }

}

function fn(item,index,arr){}

2)every 查找数组中的条件每一个是否满足条件。有就返回true,只要有一就返回false;

重构every

function everys(arr,fn){

    if(!fn) return  false

    return ture;

}

function fn(item,index,arr){}

**四.10 filter和reduce及reduceRight**

1)filter 将满足条件的元素返回一个新数组,“过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。

arr.filter(function(item,index,arr){});

重构filter

function filter1(array,fn){

            var arr1=[];

            for (var i=0;i<array.length;i++){

                if(array[i]===undefined)  continue;

                if(fn(array[i],i,array))  arr1.push(array[i]);  //如果这里用arr1[i]=array[i];  结果是[empty,2,empty,4......]

            }            //这是因为回调函数返回的是false true  false  true...,这样arr1的奇数位就是empty,但是用push,arr的奇数位就不会被复制。

            return arr1;     //这个注释可以用来区分map和filter的区别,map返回的是运算结果

        }

2)reduce,遍历数组,会将上一次的value返回给下一次的value

reduceRight()则从数组的最后一项开始,向前遍历到第一项。

arr.reduce(function(value,item,index,arr){} 初始值),如过初始值没有写的话,首先value会等于arr[0]

遍历从第一项开始,如果给了初始值,则初始值等于value,遍历从第0项开始

重构reduce(不完整版)

function reduces(arr,fn,initvalue){

    var i=0

    if(initvalue===undefined){

        initvalue=arr[0];//如果为给初始值。则默认为数组第一项

        i=1

    }

    for(i<arr.length;i++){

        var initvalue=fn(initvalue,arr[i],i;arr);//将初始值带入fn函数中,并重新定义新初始值为fn函数中数组元素。

    }

    return initvalue;

}

function fn(value,item,index,arr){}

**四.11 判断是不是数组,不能用typeof**

1)ES6中;Array.isArray(arr),是就返回true,不是返回false

**四.12 参数列表 arguments**

arguments  伪数组;只能在函数中被调用,所有的列表(类数组,伪数组)都可以通过[下标]的方式调用。

arguments是实参中的列表,arguments.callee就是当前函数,如果该函数是回调执行的,arguments.callee.caller就是回调执行当前函数外的函数

**四.13 arr的方法reverse();数组元素倒序或者反转**

var arr = [13, 24, 51, 3];

console.log(arr.reverse()); //[3, 51, 24, 13]

console.log(arr); //[3, 51, 24, 13](原数组改变)

**四.14 entries/keys/values 都取/取键/取值**

var arr=['a', 'b', 'c']

for(let key of arr.keys()){console.log(key)} //0,1,2                   

for(let value of arr.values()){console.log(value)} //a,b,c             

for(let [key, value] of arr.entries()){console.log([key,value])} //[0,'a'],[1,'b'],[2,'c']

**四.15  includes判断数组是否包含某项,返回true/false**

[1, 2, 3, 4, 5].includes(4)    //true

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352