前端JavaScript

第七天

2020-03-10  本文已影响0人  晚月川

数组

数组是引用数据类型中的对象数据类型(特殊对象)
创建一个数组,也要开辟一个堆内存,堆内存中存储数据对象中的键值对

真实项目中,我们从服务器获取到的数据,一般都是对象或者数组(JSON格式),而且结构层级一般也都是多级结构,所以学会数组/对象的相关操作,能够根据需求把获取的数据进行有效的解析和处理,是当下前端开发中非常重要的知识点;尤其是vue/react开发的时候,我们都是在不断的操作数据,来控制视图的渲染,而操作的数据也是以对象和数组偏多;...

学习数组步骤

  1. 掌握基础操作
  2. 掌握数组中常用的内置方法 (浏览器天生给数据提供的方法)
  3. 掌握数组排序和去重(算法)
    ......

获取每一项的值

数组迭代(遍历数组中的每一项)
```
for (let i = 0; i < arr.length; i++) {
    let item = arr[i];
    console.log(`当前遍历的是数组中索引为:${i},数值为:${item}的这一项!`);
}
```

作为普通对象,基于FOR IN遍历数组中所有的键值对

```
 for (let attr in arr) {
    console.log(attr, arr[attr]);
}
```

还可以基于 while循环、for of循环、内置的迭代方法来遍历数组每一项

数组中常用的内置方法

基于这些方法可以让我们有效的对数组进行操作 => console.dir(Array.proto)

let arr = [10, 20, 30];

  1. 关于数组的增删改

    • push

      • @params:参数个数不固定,类型也不固定,都是向数组末尾依次追加的内容
      • @return:[number]新增后数组的长度
      • 原始数据改变
      • 向数组末尾追加元素 => 基于键值对操作:arr[arr.length]=xxx
      let result = arr.push(40, '珠峰培训');
      console.log(result); //=>5
      
    • pop

      • 删除数组最后一项
      • @params:无
      • @return:被删除的那一项内容
      • 原始数组改变

      let result = arr.pop();

    arr.length-- 删除最后一项
    + shift
    - 删除数组第一项
    - @params:无
    - @return:被删除的那一项内容
    - 原始数组改变

     `let result = arr.shift();`
    
    • unshift

      • 向数组开始位置新增内容
      • @params:个数不定、类型不定,都是要依次新增的内容
      • @return:[number]新增后数组的长度
      • 原始数据改变

      let result = arr.unshift(0, '珠峰培训');

    • splice

      • 实现数组指定位置的增删改
        • arr.splice(n,m):从数组索引n开始,删除m个元素,返回结果是以新数组的方式,把删除的内容进行存储(m不写就是删除到末尾)
        • arr.splice(n,m,x):从索引n开始,删除m个元素,用x替换删除的内容,返回结果是一个数组,存储删除的内容
        • arr.splice(n,0,x1,x2...):从索引n开始,一个都不删除(返回结果是空数组),把x1或者更多值“插入到索引n前面”
      • 原始数组都会改变
      let arr = [10, 20, 30, 40, 50, 60, 70];
      ========新增(一个都不删)
      let result = arr.splice(2, 0, 100, 200, 300);
      console.log(result, arr); //=>result=[]  arr=[10, 20,100,200,300 ,30, 40, 50, 60, 70]
      
      ========修改(删除掉一部分,然后用一些值替换即可)
      let result = arr.splice(2, 2, '珠峰培训', '周啸天');
      console.log(result, arr); //=>result=[30,40]  arr=[10, 20, '珠峰培训','周啸天', 50, 60, 70]
      
      ========删除
      let result = arr.splice(2, 3);
      console.log(result, arr); //=>result=[30,40,50]  arr=[10,20,60,70]
      
      let result = arr.splice(0); //=>从索引零开始,删除到末尾(清空原来数组,把原来数组中的每一项都存放到新数组RESULT中)
      console.log(result, arr); //=>result=[10, 20, 30, 40, 50, 60, 70]  arr=[]
      

      需求:删除数组末尾这一项,你有几种办法?

      let arr = [10, 20, 30, 40, 50, 60, 70];

      • arr.length--;
      • arr.pop(); //=>返回结果70
      • arr.splice(arr.length - 1); //=>从最后一项开始,删除到末尾(删除一个) 返回结果[70]
      • delete arr[arr.length - 1]; //=>虽然可以删除,但是LENGTH长度不变(一般不用)
      • ...

      需求:向数组末尾追加‘珠峰’

      let arr = [10, 20, 30, 40, 50, 60, 70];

      • arr.push('珠峰');
      • arr[arr.length] = '珠峰';
      • arr.splice(arr.length, 0, '珠峰');
  2. 关于数组查询和拼接

    • slice

      • slice(n,m):实现数组的查询,从索引n开始,查找到索引m处(不包含m),把查找到的内容以新数组的方式返回,原始数组不变
        • console.log(arr.slice(2)); //=>[30, 40, 50, 60, 70] 第二个参数不写是直接查找到数组末尾
        • console.log(arr.slice(0)); //=>[10, 20, 30, 40, 50, 60, 70] 可以理解为把原始数组中的每一项都查找到,以新数组返回,实现出“数组的克隆”:得到的新数组和原始数组是两个不同的数组(两个不同的堆),但是堆中存储的内容是一致的
    • concat

      • concat:实现数组拼接,把多个数组(或者多个值)最后拼接为一个数组,原始的数组都不会变,返回结果是拼接后的新数组
      let arr1 = [10, 20, 30];
      let arr2 = [50, 60, 70];
      
      let arr = arr1.concat('珠峰', arr2);
      console.log(arr); //=>[10, 20, 30, "珠峰", 50, 60, 70]
      
  3. 转化为字符串

    • toSting
      • toString():把数组中的每一项按照“逗号分隔”,拼接成对应的字符串
    • join
      • join([char]):指定分隔符
    • 原始数组都不会改变
        console.log(arr.toString()); //=>'10,20,30,40,50,60,70'
        console.log(arr.join()); //=>等价于toString
        console.log(arr.join('+')); //=>'10+20+30+40+50+60+70'  如果这个字符串能够变为JS表达式执行,则代表数组中每一项的求和 =>eval
        let str = arr.join('+');
        let total = eval(str);
        console.log(total);
    
        let total = 0;
        for (let i = 0; i < arr.length; i++) {
            total += arr[i];
        }
        console.log(total);
    
  4. 验证是否包含某一项的

    • indexOf / lastIndexOf
      • 获取数组中指定项的索引
        • indexOf([item]):获取当前项在数组中第一次出现位置的索引
        • lastIndexOf([item]):获取当前项最后一次出现的索引
      • 如果数组中不包含这一项,则返回结果是-1
    • includes
      • 验证数组中是否包含这一项,包含返回true,不包含返回false
  5. 关于排序的

    • reverse
      • 把原始数组倒过来排列,返回的结果是排列后的原始数组
    • sort
      • 把原始数组按照规则进行排序,原始数组会改变(返回结果也是改变后的原始数组)
      • sort排序,默认不是按照每一项的数值大小排序,而是按照每一项的每一个字符编码来进行排序的,所以直接写sort,不能处理两位及两位以上的内容排序
  6. 关于数组迭代的方法(数组中常用的迭代方法)

    • forEach
      • forEach([函数]):遍历数组中的每一项(数组中有多少项,函数都会相继被执行多少次),
      • item:当前遍历的这一项内容
      • index:当前项的索引
    • map
      • forEach是不支持返回值的,而map可以在forEach的基础上支持返回值,把原来数组中每一项的值
      • item:当前循环这一次的值
      • 当前值对应的索引
      • 函数中返回啥,都是把数组中当前项替换成啥
    • 以后会涉及的:find / filter / every / some / reduce ...

数组去重的方式(12种)

数组去重就是去掉数组中的重复项

方案一:

依次遍历数组中的每一项,拿当前项和其“后面”的每一项进行比较,如果后面还有和它相同的,则说明这是重复的,我们把后面中重复的这一项删除掉即可

======================外层循环控制每一次拿出一项和其后面的比

方案二:对象键值对的方式

我们把item作为obj对象的属性名和属性值分别存储进去(每一次存储之前)
// i < arr.length - 1 最后一项不需要再拿出来了,因为每一次都是和当前项后面的比较,而最后一项后面没有任何的东西,所以也就没有必要再拿出来比较了

        for (let i = 0; i < arr.length - 1; i++) {
            // 每一次拿出来要和后面依次比较的那一项
            let item = arr[i];
            //======里层循环控制和当前项后面的每一项逐一比较
            // let j = i + 1 从当前项的后一项开始逐一比较即可
            for (let j = i + 1; j < arr.length; j++) {
                if (item === arr[j]) {
                    // 当前项和后面中的某一项相等了,此时我们把后面中的这一项从原始数组中删除掉
                    arr.splice(j, 1);
                    j--; //=>删除完,先让j--,然后在j++,相当于没加没减,下一轮还是从当前索引开始比较,这样防止数组塌陷带来的问题
                }
            }
        }
    ```
     for (let i = 0; i < arr.length - 1; i++) {
        let item = arr[i];
        for (let j = i + 1; j < arr.length; j++) {
            if (item === arr[j]) {
                // 用最后一项替换当前项
                arr[j] = arr[arr.length - 1];
                // 最后一项删掉
                arr.length--;
                // 下一轮还和这一项比(因为这一项已经变为最新的最后一项了)
                j--;
            }
        }
    }
    console.log(arr);
    ```
    let arr = [1, 2, 3, 1, 1, 4, 2, 3];
        for (let i = 0; i < arr.length - 1; i++) {
            let item = arr[i];
            for (let j = i + 1; j < arr.length; j++) {
                if (arr[j] === item) {
                    // 后面某项值和当前项相等了:直接删除
                    /* arr.splice(j, 1);
                    j--; */

                    // 原始数组中的顺序会变化,但是不会导致索引前置这种情况(性能好)
                    arr[j] = arr[arr.length - 1];
                    arr.length--;
                    j--;
                }
            }
        }
        console.log(arr);
  1. 只有一个循环,所以性能很好
  2. 如果数组中出现对象则存在问题(因为对象的属性名不能是对象,遇到会转换为字符串);如果数组中存在数字10和字符串'10',则也会认为是重复的(对象中的属性名是数字和字符串没啥区别);数组中的值如果是undefined可能也会出现问题
let arr = [1, 2, 3, 1, 1, 4, 2, 3];
        let obj = {};
        for (let i = 0; i < arr.length; i++) {
            // 把每一次循环得到的当前项,作为对象的属性名和属性值存储进去
            let item = arr[i];
            if (obj[item] !== undefined) {
                // 证明对象中有这个属性(也就是之前存储过,数组中之前就有这个值),当前值是重复的,我们需要把当前这项的值删掉即可
                arr[i] = arr[arr.length - 1];
                arr.length--;
                i--;
                continue;
            }
            obj[item] = item;
        }
        console.log(arr);

方案三:

ES6中没有提供现成的去重办法,但是提供了一些去重的方式 :Set数据结构

let obj = {
        y: 200
    };
    let arr = [obj, 1, 2, 3, 1, obj, 1, 4, 2, 3, '3', {
        x: 100
    }, {
        x: 100
    }];
    arr = Array.from(new Set(arr));
    console.log(arr);
上一篇下一篇

猜你喜欢

热点阅读