day6

96 阅读15分钟

1.数组的创建方法

数组数据类型
    + 是 JS 内的一个复杂数据类型 - Array
    + 私人: 是一个 "盒子", 是一个存储数据的 "盒子"
    + 数组是一个有序的数据集合
      => 每一个数据按照 索引 排列
      => 索引: 从 0 开始, 依次 +1

  创建数组数据类型(3种)
    + 字面量创建
      => 创建空数组: var arr = []
      => 创建带有数据的数组: var arr = [ 数据1, 数据2, 数据3, ... ]
    + 实例化创建  
      => 创建带有数据的数组: var arr=new Array(1,2,3,4,5)  
    + 构造函数创建
      => 创建数组: var arr=Array(1,2,3,4);
      
      1.创建空数组: var arr = new Array()
      2.创建带有数据的数组: var arr = new Array( 数据1, 数据2, 数据3, ... )
      3.创建指定长度的数组: var arr = new Array(数字) 这个数值只能是正整数,如果是小数或者负数时会报错

2.数组的基本操作

   数组的基本操作

  1. length 属性
    + 是一个 读写 的属性
    + 读(获取):
      => 语法: 数组名.length
      => 得到: 一个数值类型的数字, 表示数组内有多少个数据
    + 写(设置):
      => 语法: 数组名.length = 数字
      => 作用: 设置数组的长度
      => 结果:
        -> 你设置的 length 小于原始 length, 从数组的后面开始删除数据
        -> 你设置的 length 等于原始 length, 就相当于没有设置
        -> 你设置的 length 大于原始 length, 多出来的位置使用 empty 补齐

  2. 索引 属性
    + 是一个 读写 的属性
    + 读(获取):
      => 语法: 数组名[索引]
      => 得到:
        -> 如果数组内有该索引位置, 那么就是该索引位置的数据
        -> 如果数组内没有该索引位置, 那么就是 undefined
    + 写(设置):
      => 语法: 数组名[索引] = 值
      => 结果:
        -> 如果数组内有该索引位置, 那么就是修改该索引位置的数据
        -> 如果你设置的索引刚好等于 length, 那么就是追加             !!!!!!!!!!!!!!!!!!!!!
        -> 如果你设置的索引大于 length, 那么中间空余位置使用 empty 补齐
        -> 为了保证数组最后一位的索引, 一定是 length - 1

3.遍历数组

 var arr=[1,2,3,,4,undefined,5,6,7,8];
     arr.a=10;
     arr["8"]=9; //这个key[ ]里面给了数字会自动变为下标
     
 1.会遍历空元素:   不遍历a a是属性不是元素  仅遍历元素
        for(var i=0;i<arr.length;i++){
            console.log(i,arr[i]);
        }

 2.for in 可以遍历对象属性
 不能遍历空元素:    会遍历a
        for(var key in arr){
            // 会自动将下标转换为字符串
            console.log(key,arr[key]);
        }
                 
 3.既不遍历空元素 也不遍历a怎么写?                    !!!!!!!!!!!!!!!!!
        for(var i=0;i<arr.length;i++){
            // console.log(i in arr,i)
            if(i in arr) console.log(i,arr[i]); // i in arr 查看下标是否在arr中存在 空元素会被排除
        }
 
 4.for of 遍历元素中的每一个值,不关注下标,仅关注元素的值
        for(var value of arr){
            console.log(value)
        }

4.push()

+ 语法: 数组.push(数据, 数据2, ...)
+ 作用: 把参数按照顺序追加到数组的末尾
+ 返回值: 追加后数组最新的长度
例:
var arr = [ 100, 200, 300, 400, 500 ]
var res = arr.push('新来的', '新来的2')
console.log('追加以后 : ', arr)//[100, 200, 300, 400, 500, '新来的', '新来的2']
console.log('返回值 : ', res)//  7

重构:   array.constructor的意思 构造函数
function arrayPush(array){           //这个array就是我要push进去的内容
        //如果array为真 并且构造函数为Array时 是数组
        //如果array为假 并且构造函数不为Array时  不是数组  下面的解释
        if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
        for(var i=1;i<arguments.length;i++){   //循环
            array[array.length]=arguments[i]; // array.length是指最大下标的下一个坐标
                                              //array[array.lenght] 是数组后面添加新的元素
                                              //arguments[i]是指我要添加的数组的坐标
        }
        return array.length;                  //返回数组长度
    }

   var arr=[1,2,3];

   var len=arrayPush(arr,4,5,6);
   console.log(arr,len)  //[1, 2, 3, 4, 5, 6] 6

5.pop()

+ 语法: 数组.pop()
+ 作用: 删除数组的最后一个数据
+ 返回值: 被删除的数据
例:
var arr = [ 100, 200, 300, 400, 500 ]
var res = arr.pop()
console.log('删除以后 : ', arr)//[100, 200, 300, 400]
console.log('返回值 : ', res)//  500

重构:
   function arrayPop(array){
      if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
      if(array.length<=0) return;       //数组长度<=0时 直接return  undefind
      var item=array[array.length-1]; //数组最后一个元素 下标 存给item
       array.length--;                //数组长度 -1
       return item;                   //返回被删除的值
   }

   var arr=[1,2,3];
   var item=arrayPop(arr);
//    var item=arrayPop(arr);
//    var item=arrayPop(arr);
//    var item=arrayPop(arr);
   console.log(arr,item)// [1, 2] 3

6.unshift()

+ 语法: 数组.unshift(数据1, 数据2, ...)
+ 作用: 向数组的最前面插入数据
+ 返回值: 插入后数组最新的长度
例:
var arr = [ 100, 200, 300, 400, 500 ]
var res = arr.unshift('新来的')
console.log('插入之后 : ', arr)//['新来的', 100, 200, 300, 400, 500]
console.log('返回值 : ', res)//  6

重构:    //arguments.length是下面(arr,4,5,6)的长度
function arrayUnshift(array){
     if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
     for(var i=array.length+arguments.length-2;i>=0;i--){ // array.length-1 + arguments.length-1
            if(i>=arguments.length-1){                  //如果 i 大于 参数数量
                array[i]=array[i-(arguments.length-1)];//循环内 i 初始为5 依次把前面的下标元素挪过去
            }else{
                array[i]=arguments[i+1]; //挪完后 就是把剩余的参数依次添加进去(4,5,6)
            }
        }
         return array.length;     //返回长度
      }

        var arr=[1,2,3];

        var len=arrayUnshift(arr,4,5,6);
        console.log(arr,len) //[4, 5, 6, 1, 2, 3] 6

7.shift()

+ 语法: 数组.shift()
+ 作用: 删除数组最前面一个数据
+ 返回值: 被删除的数据
例:
var arr = [ 100, 200, 300, 400, 500 ]
var res = arr.shift()
console.log('删除之后 : ', arr)//[200, 300, 400, 500]
console.log('返回值 : ', res)//  100

重构:
function arrayShift(array){
            if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
            var item=array[0];     //把数组的第 0 项元素拿出来
            for(var i=0;i<array.length;i++){
                array[i]=array[i+1]; //依次前挪
            }
            array.length--;        //数组长度-1
           return item;            //返回被删除的值
        }

       var arr=[1,2,3];
       var item= arrayShift(arr);
       console.log(arr,item)

8.concat

+ 语法: 原始数组.concat(数组2, 数据3, ...)
+ 作用: 拼接数组, 追加在原始数组的最后面(数组拆开来放进去)
+ 返回值: 拼接好的新数组
例:
var arr = [ 100, 200, 300 ]
var res = arr.concat([ '数据1', '数据2' ], '数据3', ['数据4', '数据5'])
console.log('原始数组 : ', arr)//[100, 200, 300]
console.log('返回值 : ', res) //[100, 200, 300, '数据1', '数据2', '数据3', '数据4', '数据5']

重构:
function arrayConcat(array){
    if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
    var arr=[];    //准备一个新空数组
    for(var i=0;i<arguments.length;i++){   //循环遍历整个(arr,[4,5,6],[,undefined],7,8,9)每一项
    if(arguments[i] && arguments[i].constructor===Array){ //如果arguments为真 并且构造函数为Array时 是数组
            for(var j=0;j<arguments[i].length;j++){    //循环这个下面的数组
                //查看 j元素 是否在arguments中存在 如果存在就正常赋值
                if(j in arguments[i]) arr[arr.length]=arguments[i][j]; 
                else arr.length++;  //如果j元素在arguments中不存在 就创造一个空元素
            }
        }else arr[arr.length]=arguments[i]; //如果这个不是数组就直接把arguments里面第i项添加到arr里面
    }
    return arr; //返回新数组
}

var arr=[1,2,3];
var arr1=arrayConcat(arr,[4,5,6],[,undefined],7,8,9);
console.log(arr1) //[1, 2, 3, 4, 5, 6, 空白, undefined, 7, 8, 9]

9.slice()

+ 语法: 数组.slice(开始索引, 结束索引)
    => 第一个参数: 默认值是 0
    => 第二个参数: 默认值是 数组的length
+ 特点:
    => 包前不包后, 包含开始索引, 不包含结束索引
    => 可以填写负整数, 表示倒数多少个, 其实就是 length + 负整数
+ 作用: 截取数组内的部分内容
+ 返回值: 必然是一个新数组
    => 如果你没有截取内容, 那么就是一个空的新数组
    => 如果你截取了内容, 那么就是你所有截取的内容放在新数组内
例:
var arr = [ 100, 200, 300, 400, 500, 600, 700 ]
          // 0    1    2    3    4    5    6
console.log('原始数组 : ', arr)
// 从数组 [2] 位置截取到 [5] 位置, 包含 [2] 位置数据, 不包含 [5] 位置数据
var res = arr.slice(2, 5)  //[300, 400, 500]
// 从数组 [2] 位置截取到 [arr.length + -2] 位置, 包含 [2] 位置数据, 不包含 [5] 位置数据
var res = arr.slice(2, -2)    //-2 就是length - 2 (包前不包后)  //[300, 400, 500]
console.log('返回值 : ', res)

重构:
var arr=[1,2,3,4,5];
function arraySlice(array,start,end){
    if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
    var arr=[];   //创建一个新数组
    if(array.length===0) return arr;  //如果数组长度为0 
    if(start===undefined) start=0;  //如果start是undefind 直接等于0
    if(end===undefined) end=array.length;//如果end是undefind 直接到尾部
    start=~~start;                       // ~~方法 如果是非数值变成0  如果是数值变成整数
    end=~~end;  
    //start如果为负数时 如果超出长度为0 否则正常加(等于start+array.length这个长度)                            
    if(start<0) start=start+array.length<0 ? 0 : start+array.length;
    if(end<0) end=end+array.length<0 ? 0 : end+array.length;
    for(var i=start;i<end;i++){
        arr[arr.length]=array[i]; //arr当中arr.length下标添加的是array的第 i 项
    }
    return arr;  //返回这个新数组
}

var arr1= arraySlice(arr,-3,-1)//3 4
console.log(arr1)

10.splice() 麻烦

+ 语法:
   => 数组.splice(开始索引, 多少个)
   => 数组.splice(开始索引, 多少个, 要插入的数据, ...)
+ 作用: 截取数组内的部分数据, 并选择是否插入数据
+ 返回值: 必然是一个新的数组
   => 如果你截取了数据, 那么新数组内就是你截取出来的所有数据
   => 如果你没有截取数据, 那么就是一个空的新数组
+ 注意: 当你有了插入内容以后
   => 从哪一个索引位置截取, 插入哪一个索引位置
例:
var arr = [ 100, 200, 300, 400, 500, 600, 700 ]

1. 开始截取
// 表示从 [2] 开始, 截取 3 个数据
var res = arr.splice(2, 3)
console.log('截取之后 : ', arr)//[100, 200, 600, 700]
console.log('返回值 : ', res)//[300, 400, 500]

2. 截取并插入
// 表示从 [2] 开始, 截取 1 个数据, 把 '新来的' 插入到 [2] 位置
var res = arr.splice(2, 1, '新来的', '新来的2')
console.log('截取之后 : ', arr)//[100, 200, '新来的', '新来的2', 400, 500, 600, 700]
console.log('返回值 : ', res)//[300]

3.截取0个  返回空数组
var res = arr.splice(2, 0, '新来的')
console.log('截取之后 : ', arr)//[100, 200, '新来的', 300, 400, 500, 600, 700]
console.log('返回值 : ', res)//[]

重构:
 function arraySplice(array,start,deleteCount,...item){  //item剩余参数 是一个数组 deleteCount删除几个
   if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
   var deleteArr=[];  //创建一个空数组 保存被删除的元素

   1.开始位置 start
   if(start===undefined) return deleteArr;//如果start是undefind 直接返回空数组 不做任何处理
   start=~~start;  // ~~方法 如果是非数值变成0  如果是数值变成整数
   if(start<0) start=start+array.length<0 ? 0 : start+array.length;//如果是负数时
   if(start>array.length) start=array.length;

   2.删除个数 deleteCount
   if(deleteCount===undefined) deleteCount=array.length-start;//如果deleteCount为undefind 数组长度-开始索引
   deleteCount=~~deleteCount;
   if(deleteCount<0) deleteCount=0;//如果deleteCount小于0  就当他是0

   3.挪的问题(因为不能确定插得个数比截取的个数多)
   for(var i=start;i<array.length;i++){
     if(i<start+deleteCount){
     deleteArr[deleteArr.length]=array[i];//将删除的值 按顺序放在被删除数组中
          }
      array[i]=array[i+deleteCount];//剩下的未被删除的数值 往前挪
     }

   4.删除的个数可能比我从开始往后数的个数多  会造成删除个数超出范围 所以最大删除个数就是从开始到数组结尾
    //如果array.length 大于 当前数组的下标(array.length-start) 时 那么就等于这个值否则删除对应值
    array.length-=deleteCount>array.length-start ? array.length-start :deleteCount; //截取后数组长度减小

    5.添加 item
    for(var j=array.length+item.length-1;j>=start;j--){
        if(j>=start+item.length){
             //截取后数组长度减小 这时要插入数据 从start开始 原本start索引位置的数据 要向后挪插入数据的个数的位置
             array[j]=array[j-item.length];//把前面的向后挪
        }else{ 
                array[j]=item[j-start]; //把后面的向前挪 j是当前项
            }
        }
        return deleteArr;  //返回被删除的数值 组成的数组
    }

   var arr=["a","b","c","d","e","f","g"];
   var arr1=arr.splice(2,2);
   console.log(arr,arr1)//(5) ['a', 'b', 'e', 'f', 'g'] (2) ['c', 'd']

   var arr2=["a","b","c","d","e","f","g"];
   var arr3=arraySplice(arr2,2,2)
   console.log(arr2,arr3)//['a', 'b', 'e', 'f', 'g'] (2) ['c', 'd']

11.join()

+ 语法: 数组.join(连接符)
    => 连接符默认使用 逗号(,)
+ 作用: 使用连接符把数组的每一项连接成字符串
+ 返回值: 连接好的字符串
例:
var arr = [ 2022, 4, 19 ]
console.log('原始数组 : ', arr)
var res = arr.join(' @-@ ')
console.log('返回值 : ', res) // 2022 @-@ 4 @-@ 19
console.log('返回值 : ', typeof res) //string

重构:
function arrayJoin(array,separator){
        if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
        if(separator===undefined) separator="," //如果符号为undefind 默认为 , 
        separator+="";    //把他变成一个空字符串
        var str="";       //定义一个空字符串
        for(var i=0;i<array.length;i++){
             //如果说是最后一项加空字符串 如果不是加拼接符
             str+=array[i]+(i===array.length-1 ? "" : separator);
        }
        return str;
    }

    var str=arrayJoin(arr,false);
    console.log(str)

12.arr.at(下标)

返回下标对应的元素,如果下标为负数,返回倒数第几项
例:
var arr=[1,2,3,4];
console.log(arr.at(-1)); // 4

重构:
function arrayAt(array,index){
       if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
       if(index===undefined) index=0; //如果index是undefind 就让他为0 
       index=~~index; // ~~方法 如果是非数值变成0  如果是数值变成整数
       if(index<0) index=index+array.length<0 ? 0 : index+array.length;//如果是负数时
       return array[index];//返回array对应的index数值
    }

13.fill(填充的内容,开始位置,结束位置)

填充 根据数组的长度来填充数据 默认填充空属性
例:
 var arr=[1,2,3];
 vrr.fill(1); //[1,1,1]

 var arr=[];
 arr.fill(1);
 console.log(arr) //[]

 var arr=Array(6);
 arr.fill({a:1}); //填入是同一个对象
 console.log(arr[0]===arr[1]) //true

 arr.fill(1,2,6);
 console.log(arr) //[{…}, {…}, 1, 1, 1, 1]
 
重构:
function arrayFill(array,value,start,end){
        if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
        if(array.length===0) return array;//如果数组长度为0 
        if(start===undefined) start=0;//如果start是undefind 直接等于0
        if(end===undefined) end=array.length;//如果end是undefind 直接到尾部
        start=~~start; // ~~方法 如果是非数值变成0  如果是数值变成整数
        end=~~end;
        if(start<0) start=start+array.length<0 ? 0 : start+array.length;
        if(end<0) end=end+array.length<0 ? 0 : end+array.length;
        //填充时
        for(var i=start;i<end;i++){
            array[i]=value;
        }
        return array;
    }

    var arr=Array(6);
    arrayFill(arr,1,2)
    console.log(arr) //[空属性 × 2, 1, 1, 1, 1]

14.indexOf()

+ 语法:
     => 数组.indexOf(要查找的数据)
     => 数组.indexOf(要查找的数据, 开始索引)
+ 作用: 按照正序的索引顺序, 查找数据在数组中第一次出现的索引位置
+ 返回值:
     => 如果找到了该数据, 那么就是该数据第一次出现的索引位置
     => 如果没有该数据, 那么就是 -1
例:
var arr = [ 1, 2, 3, 4, 1, 2, 3, 1, 2, 1 ]
console.log('原始数组 : ', arr) //[1, 2, 3, 4, 1, 2, 3, 1, 2, 1]
// 从 arr 数组中查找是否有 2 这个数据
var res = arr.indexOf(2)
// 表示从 [2] 位置开始向后查找 arr 数组中是否有 2 这个数据
var res = arr.indexOf(2, 2) //5
// var res = arr.indexOf(2, 9) //-1
console.log('返回值 : ', res)

重构:
function arrayIndexOf(array,item){   //item 要查找的元素
    var index=-1; //默认index=-1
    for(var i=0;i<array.length;i++){ 
    if(i in array && array[i]===item) return i;//判断 i in arr如果 i 在数组arr中存在(不是空元素的话)
        }
    return index;
    }
    var arr=[1,2,3,,4,undefined,5,3,6];
    var index=arrayIndexOf(arr);
    console.log(index) //5   

14.LastindexOf()

+ 语法:
    => 数组.lastIndexOf(要查找的数据)
    => 数组.lastIndexOf(要查找的数据, 开始索引)
+ 作用: 按照倒序的索引顺序, 查找数据在数组中第一次出现的索引位置
+ 返回值:
    => 如果找到了该数据, 那么就是该数据第一次出现的索引位置
    => 如果没有该数据, 那么就是 -1
例:
var arr = [ 1, 2, 3, 4, 1, 2, 3, 1, 2, 1 ]
console.log('原始数组 : ', arr)
// 表示从 arr 数组的最后一个索引开始向前查找 2 这个数据
var res = arr.lastIndexOf(2)//8
var res = arr.lastIndexOf(2, 0)  //从0开始往左找
console.log('返回值 : ', res)//-1

重构: 
 function arraylastIndexOf(array,item){
        var index=-1;
        for(var i=array.length-1;i>=0;i--){ //同indexOf 倒着循环罢了
            if(i in array && array[i]===item) return i;
        }
        return index;
    }

15. Array.isArray();

判断是否是数组
重构:
function isArray(array){    // !!array 意思是转换成布尔值 或者这样写 Boolean(array)
return !!array && array.constructor===Array; //判断 array 如果为真 
    }         
console.log(isArray(0));

16.Array.from();

将非数组列表转换为数组 (将迭代器转换为数组)
例:
function fn(){
    var arr=Array.from(arguments);
    console.log(arr)
    }
    fn(1,2,3,4,5); //[1,2,3,4,5,]
    
重构:多种方式
1. function arrayFrom(list){
        var arr=[];
        // for(var i=0;i<list.length;i++){
        //     arr[arr.length]=list[i];
        // }
        for(var value of list){
            arr[arr.length]=value;
        }
        return arr;
    }
    
2.function arrayFrom(list){
       return [].slice.call(list);
    }
    
3.function arrayFrom(list){
       return [].concat.apply([],list);
    }

17.forEach()

+ 语法: 数组.forEach(function (item, index, arr) {})
+ 作用: 遍历数组
+ 返回值: 没有
例:
var arr = [ 100, 200, 300, 400, 500 ]
arr.forEach(function (item, index, arr) {
  // 第一个形参: 表示数组内的每一项
  // 第二个形参: 表示数组内每一项的索引
  // 第三个形参: 表示原始数组
  console.log(item, index, arr)
})

重构:
function arrayForEach(array,fn){      //写了个回调函数 fn
      if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
      if(typeof fn!=="function")  throw new TypeError(fn+" is not a function");
        for(var i=0;i<array.length;i++){
            if(i in array)  fn(array[i],i,array); // i in arr 查看下标是否在arr中存在 空元素会被排除      
        }                   //此处forEach只管执行            //array[i]当前元素  i下标 array数组本身
    } 

    arrayForEach(arr,function(item,index,arr){
        console.log(item,index,arr)
    })

18.map()

+ 语法: 数组.map(function (item, index, arr) {})
+ 作用: 映射数组
+ 返回值: 是一个新的数组
   => 和原始数组一模一样的长度
   => 只不过每一个数据都是被操作过后的数据
+ 注意: 映射条件使用 return 的形式书写
例;
var arr = [ 100, 200, 300, 400 ]
console.log('原始数组 : ', arr)
var res = arr.map(function (item, index, arr) {
  // 以 return 的形式书写映射条件
  return item * 100
})
console.log('映射之后 : ', res)//[10000, 20000, 30000, 40000]

重构:
var arr=[1,2,,3,4,5];
    function arrayMap(array,fn){          //写了个回调函数 fn
        if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
         if(typeof fn!=="function")  throw new TypeError(fn+" is not a function");
        var arr=[];               //准备一个空数组
        for(var i=0;i<array.length;i++){  //for 循环
            // 将函数返回的值存储在新数组中对应的下标位置
            if(i in array) arr[i]=fn(array[i],i,array) //i in arr 查看下标是否在arr中存在 空元素会被排除      
        }                                             //把return返回的结果 放在arr当中对应的那一项
        return arr;
    }

    // 这种写法都叫做桥接模式
   var arr1=arrayMap(arr,function(item,index,arr){
        return item+10;
    })
   console.log(arr1)

19.every()

+ 语法: 数组.every(function (item, index, arr) {})
+ 作用: 判断数组内是否每一个都满足条件
+ 返回值: 是一个布尔值
   => 如果为 true, 说明数组中每一个都满足条件
   => 如果为 false, 说明数组中至少有一个不满足条件
+ 注意: 以 return 的形式书写 判断条件
例:
var arr = [ 100, 200, 300, 400, 500 ]
var res = arr.every(function (item) {
  return item > 100
})
console.log('返回值 : ', res) //false

重构:
function arraySome(array,fn){
        if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
        if(typeof fn!=="function")  throw new TypeError(fn+" is not a function");
        for(var i=0;i<array.length;i++){
            if(!(i in array)) continue;  //i in arr 如果下标在arr中不存在(也就是空元素) 直接continue    
            //fn(array[i],i,array) 里面 i,array是没用的 满足ruturn控制条件就行
            if(fn(array[i],i,array)) return true; //遍历数组看是否满足下述条件 如果得到的结果为true 返回true                                    
        }
        return false;                            //否则返回false
    }
  var bool=arraySome(arr,function(item,index,arr){
        return item>4                         //条件
    })
    console.log(bool)

20.some()

+ 语法: 数组.some(function (item, index, arr) {})
+ 作用: 判断数组中是否有某一个满足条件的
+ 返回值: 一个布尔值
   => true, 说明数组中至少有一个满足条件
   => false, 说明数组中所有项都不满足条件
+ 注意: 以 return 的形式书写 判断条件
例:
var arr = [ 100, 200, 300, 400, 500 ]
var res = arr.some(function (item) {
  return item > 500
})
console.log('返回值 : ', res) //false

重构:    every重构小修改
function arrayEvery(array,fn){
        if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
        if(typeof fn!=="function")  throw new TypeError(fn+" is not a function");
        for(var i=0;i<array.length;i++){
            if(!(i in array)) continue;
            if(!fn(array[i],i,array)) return false;
        }
        return true;
    }

21.filter()

+ 语法: 数组.filter(function (item, index, arr) {})
+ 作用: 对原始数组进行过滤, 拿出来满足条件的项
+ 返回值: 是一个新的数组
   => 新数组内是原始数组中所有满足条件的项
+ 注意: 以 return 的形式返回 过滤条件
例:
var arr = [ 100, 200, 300, 400 ]
console.log('原始数组 : ', arr)
var res = arr.filter(function (item) {
  // 筛选原始数组中所有大于 200 的项
  // 原理: 随着循环, 这个函数会被重复执行
  // 当 return 的内容为 true 的时候, 当前这个 item 加入到新数组
  // 当 return 的内容为 false 的时候, 当前这个 item 不加入到新数组
  return item > 200
})
console.log('返回值 : ', res) //[300, 400]

重构:
function arrayFilter(array,fn){
        if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
        if(typeof fn!=="function")  throw new TypeError(fn+" is not a function");
        var arr=[]   //新建一个空数组
        for(var i=0;i<array.length;i++){
    //如果满足条件 则为true  把当前这个元素array[i]赋值给arr[arr.length] 也就是新增到arr数组的尾部  叫做筛选
            if(i in array && fn(array[i],i,array)) arr[arr.length]=array[i];// i in array表示为空元素时不循环不遍历
        }
        return arr;   //返回创建好的新数组
    }

    var arr1=arrayFilter(arr,function(item){
        return item>5;
    });
    console.log(arr1)

22.reduce() 麻烦

+ 语法: 数组.reduce(function (prev, item, index, arr) {}, 初始值)
  => 第一个参数: 回调函数
  => 第二个参数: 初始值, 如果不传递初始值, 那么自动使用数组 [0] 位置数据
+ 作用: 用于叠加的
+ 返回值: 叠加后的结果
+ 注意: 以 return 的形式书写 叠加效果

说明:
+ 当你传递了 初始值 的时候
   => 第一次 prev 就是初始值, item 是 [0]
   => 第二次 prev 是第一次 return 的内容, item 是 [1]
   => ...
+ 当你不传递 初始值 的时候
   => 第一次 prev 就是 [0] 位置的数据, item 是 [1]
   => 第二次 prev 是第一次 return 的内容, item 是 [2]
例:
var arr = [ 100, 200, 300, 400, 500 ]
//1. 传递初始值    结果不变但是过程不同
var res = arr.reduce(function (prev, item) {
  console.log(prev, item)
  return prev + item           //1500
}, 0)

//2. 不传递初始值
var res = arr.reduce(function (prev, item) {
  console.log(prev, item)
  return prev + item       //1500
})
console.log('返回值 : ', res) 

重构:  就一个前面是空值的小bug  如:[,,,1,2,3,4]
function arrayReduce(array,fn,initValue){
        if(!array || array.constructor!==Array) throw new TypeError(array+"不是数组");
        if(typeof fn!=="function")  throw new TypeError(fn+" is not a function");
        var index=0;

        //解决 前面的值如果是空值的bug
        var bool=false;
        if(initValue===undefined){
            bool=true;
            //这一块的目的是为了查找数组能找到的第一个存在的不是空值的元素
            while(index<array.length){
                if(index in array){
                    bool=false;   //其他存在的数值 返回的布尔值是 false
                    initValue=array[index];
                    index++;
                    break;
                }
                index++;
            }
        }
        //如果这句话出现 就是循环完了 但是数组里面全是空值
        if(bool) throw new TypeError("Reduce of empty array with no initial value")
        
        for(;index<array.length;index++){
            //如果index在array中存在  就进行归并运算
            if(index in array) initValue=fn(initValue,array[index],index,array);
        }
        return initValue;
    }

    var arr=[1,2,3];
    var s= arrayReduce(arr,function(value,item){
    return value+item;   
    });
    console.log(s)//6

23.find() 家族

语法: 数组.find(function (item, index, arr) {})
   + 作用: 在原始数组中查找第一个满足条件的项
   + 返回值: 原始数组中满足条件的这一项
   + 注意: 以 return 的形式书写 查找 条件
例:
var arr = [ 10, 200, 303, 403, 500 ]
var res = arr.find(function (item, index, arr) {
  // console.log(item, index, arr)
  return item % 2 === 1
})
console.log('返回值 : ', res) //303

重构:
var arr=[
        {id:1001,name:"商品1",price:1020},
        {id:1002,name:"商品2",price:2020},
        {id:1003,name:"商品3",price:3020},
        {id:1004,name:"商品4",price:4020},
        {id:1005,name:"商品5",price:5020},
        {id:1006,name:"商品6",price:6020},  
       ]   

function arrayFind(array,fn){
        if(!array || array.constructor!==Array) throw new TypeError(array+"not is Array!");
        if(typeof fn!=="function") throw new TypeError(fn+"is not function!");
        for(var i=0;i<array.length;i++){  
            if(fn(array[i],i,array)) return array[i]; //如果找到了 返回这个数值
        }
        return null; //否则返回null
    }

    var obj=arrayFind(arr,function(item){
        return item.id===1004
    })
    
console.log(obj) //{id: 1004, name: '商品4', price: 4020}

24.findIndex()

 语法: 数组.findIndex(function (item, index, arr) {})
   + 作用: 在原始数组中查找第一个满足条件的项的索引
   + 返回值: 找到的数据的索引
   + 注意: 以 return 的形式书写 查找 条件
 例:
var arr = [ 100, 200, 303, 403, 500 ]
console.log('原始数组 : ', arr)
var res = arr.findIndex(function (item) {
  return item % 2 === 1
})
console.log('返回值 : ', res)//2

重构:
 var arr=[
        {id:1001,name:"商品1",price:1020},
        {id:1002,name:"商品2",price:2020},
        {id:1003,name:"商品3",price:3020},
        {id:1004,name:"商品4",price:4020},
        {id:1005,name:"商品5",price:5020},
        {id:1006,name:"商品6",price:6020},  
       ]   
 //这里
 function arrayFindIndex(array,fn){
        if(!array || array.constructor!==Array) throw new TypeError(array+"not is Array!");
        if(typeof fn!=="function") throw new TypeError(fn+"is not function!");
        for(var i=0;i<array.length;i++){
            if(fn(array[i],i,array)) return i; //如果找到了 返回这个数值的索引
        }
        return -1; //否则返回 -1
    }

    var obj=arrayFindIndex(arr,function(item){
        return item.id===1004
    })
    console.log(obj)//3

25.findLast()

语法: 数组.find(function (item, index, arr) {})
   + 作用: 在原始数组中查找第一个满足条件的项(从后往前找)
   + 返回值: 原始数组中满足条件的这一项
   + 注意: 以 return 的形式书写 查找 条件
例:
var arr = [ 100, 200, 303, 403, 500 ,1 ]
console.log('原始数组 : ', arr)
var res = arr.findLast(function (item) {
  return item % 2 === 1
})
console.log('返回值 : ', res)//1

重构:
var arr=[
        {id:1001,name:"商品1",price:1020},
        {id:1002,name:"商品2",price:2020},
        {id:1003,name:"商品3",price:3020},
        {id:1004,name:"商品4",price:4020},
        {id:1005,name:"商品5",price:5020},
        {id:1006,name:"商品6",price:6020},  
       ]
//这里      
function arrayFindLast(array,fn){
        if(!array || array.constructor!==Array) throw new TypeError(array+"not is Array!");
        if(typeof fn!=="function") throw new TypeError(fn+"is not function!");
        for(var i=array.length-1;i>=0;i--){       //从后往前循环
            if(fn(array[i],i,array)) return array[i];  //返回值
        }
        return null;
    }
    
 var obj=arrayFindLast(arr,function(item){
        return item.id===1002
    })
 console.log(obj)

26.findLastIndex()

语法: 数组.find(function (item, index, arr) {})
   + 作用: 在原始数组中查找第一个满足条件的项(从后往前找)
   + 返回值: 原始数组中满足条件的这一项
   + 注意: 以 return 的形式书写 查找 条件
例:
var arr = [ 100, 200, 303, 403, 500 ,1 ]
console.log('原始数组 : ', arr)
var res = arr.findLastIndex(function (item) {
  return item % 2 === 1
})
console.log('返回值 : ', res)//5

重构:
var arr=[
        {id:1001,name:"商品1",price:1020},
        {id:1002,name:"商品2",price:2020},
        {id:1003,name:"商品3",price:3020},
        {id:1004,name:"商品4",price:4020},
        {id:1005,name:"商品5",price:5020},
        {id:1006,name:"商品6",price:6020},  
       ]
//这里      
function arrayFindLast(array,fn){
        if(!array || array.constructor!==Array) throw new TypeError(array+"not is Array!");
        if(typeof fn!=="function") throw new TypeError(fn+"is not function!");
        for(var i=array.length-1;i>=0;i--){       //从后往前循环
            if(fn(array[i],i,array)) return i;  //返回值的索引
        }
        return -1;
    }
    
var obj=arrayFindLastIndex(arr,function(item){
        return item.id===1002
    })
console.log(obj) //1   

27.include()

语法: 数组.include(function (item, index, arr) {})
   + 作用: 判断数组中是否包含有3这个元素  ES6
   + 返回值: truefalse
   + 注意: 以 return 的形式书写 查找 条件
例:
var arr=[1,2,3,4,5];
console.log(arr.includes(3));//true

重构:
var arr=[1,2,3,4,5];
function arrayIncludes(array,item){
    if(!array || array.constructor!==Array) throw new TypeError(array+"not is Array!");
    for(var i=0;i<array.length;i++){
    if(i in array && array[i]===item) return true;//如果这个数存在且是要寻找的值 返回true
        }
        return false
    }

var obj=arrayIncludes(arr,3)
console.log(obj)//true

28.当在数组中查找时 (几个数组用法的对比)

1.如果需要判断有没有这个数值或者字符或者布尔值这种 非引用地址的元素 时 使用includes
2.如果需要获取这个数值或者字符或者布尔值这种 非引用地址元素的 下标时  使用indexOf
3.如果需要从后向前获取这个数值或者字符或者布尔值这种 非引用地址元素的 下标时  使用lastIndexOf
4.如果需要获取数组中某个引用元素是否 满足某个条件的 元素,使用find
5.如果需要获取数组中某个引用元素是否 满足某个条件的 元素下标,使用findIndex
6.如果需要从后向前获取数组中某个引用元素是否 满足某个条件的 元素,使用findLast
7.如果需要从后向前获取数组中某个引用元素是否 满足某个条件的 元素下标,使用findLastIndex
8.如果需要获取到数组中 所有 满足条件的元素 时,使用筛选 filter

29.flatMap()

 + 语法: 数组.flatMap()
 + 作用: 只扁平一层 还具有map功效(能对数据进行处理)
 + 返回值: 是一个新的数组
  => 和原始数组一模一样的长度 
  => 只不过每一个不是数组的数据都是被操作过后的数据 
 + 注意: 映射条件使用 return 的形式书写
例:
var arr=[
        [1,2,3],4,5,[6,7,8],[9,[10,11]]
    ]
    
var arr1=arr.flatMap(function(item){
  if(!Array.isArray(item)) return item+100; //如果是非数组 对该数据进行操作
    return item;
});
console.log(arr1)// [1, 2, 3, 104, 105, 6, 7, 8, 9, Array(2)]

重构:
var arr=[
        [1,2,3],4,5,[6,7,8],[9,[10,11]]
    ]
    function arrayFlatMap(array,fn){
        if(!array || array.constructor!==Array) throw new TypeError(array+"not is Array!");
        if(typeof fn!=="function") throw new TypeError(fn+"is not function!");
        var arr=[]; //准备个空数组
        for(var i=0;i<array.length;i++){ //循环遍历数组
            arr=arr.concat(fn(array[i],i,array)); //对数组数据进行拼接 默认 ,拼接 
        }
        return arr;
    }

    var arr1=arrayFlatMap(arr,function(item){
    if(!Array.isArray(item)) return item+100; //如果是非数组 对该数据进行操作
        return item;
    })
console.log(arr1)//[1, 2, 3, 104, 105, 6, 7, 8, 9, Array(2)]

30.flat(扁平化几层)

 语法: 数组.flat(层数)  默认一层
 + 作用: 扁平化数组
 + 返回值: 扁平好的数组
 + 注意: 以 return 的形式书写 查找 条件
例:
var arr=[
        [1,2,3],4,5,[6,7,8],[9,[10,11,[12,13]]]
    ]
var arr1=arr.flat();//[1, 2, 3, 4, 5, 6, 7, 8, 9, Array(3)]
var arr1=arr.flat(2);//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, Array(2)]
var arr1=arr.flat(3);//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
console.log(arr1)

重构:
function arrayFlat(array,maxLv,currentLv,result){
    if(!array || array.constructor!==Array) throw new TypeError(array+"not is Array!");
    if (maxLv === undefined) maxLv = 1; //如果最大深度为undefined 默认是1
    if (currentLv === undefined) currentLv = 0;//如果当前深度为undefined 默认是0
    if(result===undefined) result=[];//如果扁平化层数为undefined 直接给空数组
    for(var i=0;i<array.length;i++){
        //判断最大深度是否 大于 当前深度 且是否是数组 如果返回为true 进行扁平化处理(递归)
        if(maxLv>currentLv && Array.isArray(array[i])) arrayFlat(array[i],maxLv,currentLv+1,result);
        else result.push(array[i]); //如果不是直接加到数组最后
    }
    return result;
}

var arr1=arrayFlat(arr,2);//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, Array(2)]
console.log(arr1)

31.copyWithin(第几位开始换, 下标几开始 , 下标几结束)

 【下标几开始,下标几结束】这个代表换什么
 返回一个新数组
例:
var arr=[1,2,3,4,5,6,7,8];
// 改变原数组
var arr1= arr.copyWithin(0,1,3); //ES6 [2, 3, 3, 4, 5, 6, 7, 8]
var arr1= arr.copyWithin(0,2,4); //[3, 4, 3, 4, 5, 6, 7, 8]
var arr1= arr.copyWithin(0,1); //[2, 3, 4, 5, 6, 7, 8, 8]
console.log(arr1);

重构:
function arrayCopyWidthin(array,target,start,end){
        if(!array || array.constructor!==Array) throw new TypeError(array+"not is Array!");
        var arr=[];
        
        if(target===undefined) target=0; //第几位开始换为undefind 默认 0
        if(start===undefined) start=0;  //开始为undefind 默认 0
        if(end===undefined) end=array.length;//结束为undefind 默认 数组最大长度
        target=~~target;     // ~~方法 如果是非数值变成0  如果是数值变成整数
        start=~~start;
        end=~~end;
        if(target<0) target=target+array.length<0 ? 0 : target+array.length;
        if(start<0) start=start+array.length<0 ? 0 : start+array.length;
        if(end<0) end=end+array.length<0 ? 0 : end+array.length;
        
         //4.循环遍历
        for(var i=0;i<array.length;i++){
                                                    //灵魂替换
            if(i>=target && i<target+(end-start))  arr[i]=array[start+(i-target)]; 
           else arr[i]=array[i]; //否则直接赋值到准备好的新数组
        }
        array=arr;
        return array;
    }
    var arr=[1,2,3,4,5,6,7,8];
    var arr1= arrayCopyWithin(arr,3,1,5);
    console.log(arr1) 

32.reverse()

+ 语法: 数组.reverse()
+ 作用: 反转数组
+ 返回值: 反转以后的数组
例:
var arr=[2,5,1,3,6];
arr.reverse(); //[6, 3, 1, 5, 2]

重构:
function arrayReverse(array){
         //除2取整
        for(var i=0;i<~~(array.length/2);i++){
            var temp=array[i];
            array[i]=array[array.length-1-i];
            array[array.length-1-i]=temp;
        }
        return array;
    }

arrayReverse(arr);
console.log(arr)

31.sort()

+ 语法:
   => 数组.sort()
    -> 按照一位一位来进行排序, 按照 ASCII 码进行排序
   => 数组.sort(function (a, b) { return a - b })
    -> 按照数字大小, 从小到大升序排列
   => 数组.sort(function (a, b) { return b - a })
    -> 按照数字大小, 从大到小降序排列
+ 作用: 对数组进行排序
+ 返回值: 排序好的数组
例:
var arr = [ 1, 5, 7, 3, 11, 32, 10, 103, 71, 22 ]
  // 排序语法1 按每一位数值升序
var res = arr.sort()
console.log('排序之后 : ', arr) //[1, 10, 103, 11, 22, 3, 32, 5, 7, 71]
 // 排序语法2 按数值升序
var res = arr.sort(function (a, b) { return a - b })
console.log('排序(升序)之后 : ', arr) //[1, 3, 5, 7, 10, 11, 22, 32, 71, 103]
 // 排序语法3 按数值降序
var res = arr.sort(function (a, b) { return b - a })
console.log('排序(降序)之后 : ', arr) //[103, 71, 32, 22, 11, 10, 7, 5, 3, 1]

重构:
var arr = [2, 5, 1, 7, 18, 1, 2, 9, 5, 3, 12, 11, 2, 13];
function sort(array, fn) {
        for (var i = 0; i < array.length - 1; i++) {
            for (var j = 0; j < array.length - 1 - i; j++) {
                //array[j]参数a   array[j+1]参数b
                if (fn(array[j],array[j+1])>0) { //相当于array第j项赋值给了a  array[j+1]赋值给了b
                    var temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
        return array;
    }
    //2从小到大
    // arr[j] > arr[j + 1]  
    // arr[j]-arr[j + 1]>0

    //3.从大到小
    // arr[j+1]>arr[j] 
    // arr[j+1]-arr[j]>0

    sort(arr,function(a,b){
        return a-b;     //此处返回的是 升序
    })
    console.log(arr)