美文网首页
JS Array 对象——(1)

JS Array 对象——(1)

作者: 神奇作手 | 来源:发表于2019-08-13 10:44 被阅读0次

    一、Array 对象

      Array 对象用于在变量中存储多个值;数组是一种具有相同类型值的集合,它的每一个值称为数组的一个元素。数组用于在内存中存储大量相同类型的数据,可以通过数组的名称和下标来访问数组中的元素。

    二、数组属性

    属 性 含 义
    constructor         引用数组对象的构造函数
    length       返回数组元素的个数。如果在创建数组时指定了数组的长度,那么无论数组元素中是否超出了实际数据,该属性的值都是这个指定的长度值
    prototype       用于在定义数组时添加新的属性和方法。Prototype 是数组对象的静态属性。

    三、Array对象方法

    序 号 方法 描述
    1 concat()   连接两个或更多的数组,并返回结果;
    2 conpyWithin()   浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度;
    3 entries()   从原数组创建一个可迭代对象, 该对象包含了数组的键/值对
    4 every()   测试一个数组内的元素是否都能通过某个指定函数的测试,返回一布尔值;
    5 fill()   用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引;
    6 filter()   创建一个新数组, 其包含通过所提供函数实现的测试的所有元素
    7 find()   返回数组中满足提供的测试函数的第一个元素的值,否则返回 undefined
    8 findIndex()   返回数组中满足提供的测试函数的第一个元素的索引,否则返回-1
    9 flat()   按照一个可指定的深度递归遍历数组,将嵌套数组和原数组组合成一维数组返回;
    10 flatMap()   首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 和 深度值1的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些;
    11 forEach()   对数组的每个元素都执行一次回调函数;
    12 from()   从一个类似数组或可迭代的对象中创建一个新的、浅拷贝的数组实例;
    13 includes()   判断一个数组是否包含一个指定的值,包含则返回 true,否则返回false;
    14 indexOf()   在数组中找到给定的元素的第一个索引,如果找不到,则返回-1。
    15 isArray()   判断对象是否为数组;
    16 join()   把数组的所有元素放入一个字符串;
    17 keys()   返回数组的可迭代对象,包含原始数组的键(key);
    18 lastIndexOf()   搜索数组中的元素,并返回它最后出现的位置索引,没有则返回-1;
    19 map()   通过指定函数处理数组的每个元素,并返回处理后的数组;
    20 pop()   删除数组的最后一个元素并返回删除的元素;
    21 push()   向数组的末尾添加一个或更多元素,并返回新的长度;
    22 reduce()   将数组元素计算为一个值(从左到右);
    23 reduceRight()   将数组元素计算为一个值(从右到左);
    24 reverse()   反转数组的元素顺序;
    25 shift()   删除并返回数组的第一个元素;
    26 slice()   选取数组的的一部分,并返回一个新数组;
    27 some()   检测数组元素中是否有元素符合指定条件;
    28 sort()   对数组的元素进行排序;
    29 splice()   从数组中添加或删除元素;
    30 toString()   把数组转换为字符串,并返回结果;
    31 unshift()   向数组的开头添加一个或更多元素,并返回新的长度;
    32 values() 返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值;

    具体用法:

    1、concat() 的使用

       用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组

    语法: var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])

    参数:
      |---valueN 可选,将数组和/或值连接成新数组。详情请参阅下文描述;

    返回值:
      |---新的Array实例。

      合并三个数组的值

       var arr1 = ["A", "B"];
       var arr2 = ["a", "b", "c"];
       var arr3 = ["Aa"];
       var arr4 = t1.concat(t2,t3);
    结果:
           arr4 = ["A", "B", "a", "b", "c", "Aa"]
    
    2、conpyWithin() 的使用

      浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度。

    语法:arr.copyWithin(target[, start[, end]])

    参数:
      |--- target:复制序列开始的位置(即,原数据保留的元素位置),负数target 将从末尾开始计算,如果 target 大于等于 arr.length,将会不发生拷贝;
      |--- start:复制元素的起始位置。如果是负数,start 将从末尾开始计算,如果 start 被忽略,将会从0开始复制;
      |--- end:复制元素的结束位置,将会拷贝到该位置,但不包括 end 这个位置的元素。如果是负数,将从末尾开始计算,如果 end 被忽略,将会一直复制至数组结尾;

    返回值:
      |--- 改变后的数组。

    实例:Array.conpyWithin()

      let numbers = [1, 2, 3, 4, 5];
    
      numbers.copyWithin(-2);
      // [1, 2, 3, 1, 2]
    
      numbers.copyWithin(0, 3);
      // [4, 5, 3, 4, 5]
    
      numbers.copyWithin(0, 3, 4);
      // [4, 2, 3, 4, 5]
    
      numbers.copyWithin(-2, -3, -1);
      // [1, 2, 3, 3, 4]
    
    
    3、entries() 的使用

      从数组 arr 创建一个可迭代对象, 该对象包含了数组的键值对

    语法:arr.entries()

    返回值:
      |--- 一个新的 Array迭代器对象。Array Iterato是对象,它的原型(proto:Array Iterator)上有一个next 方法,可用用于遍历迭代器取得原数组的[key,value]。

    实例1:Array.entries()

      var array1 = ['a', 'b', 'c'];
      var iterator1 = array1.entries();
      console.log(iterator1.next().value);
      //  [0, "a"]
      console.log(iterator1.next().value);
      //  [1, "b"]
    

    实例2:iterator.next()

      var arr = ["a", "b", "c"];
      var iterator = arr.entries();
      console.log(iterator.next());
    
      /*{value: Array(2), done: false}
              done:false
              value:(2) [0, "a"]
               __proto__: Object
      */
      // iterator.next()返回一个对象,对于有元素的数组,
      // 是next{ value: Array(2), done: false };
      // next.done 用于指示迭代器是否完成:在每次迭代时进行更新而且都是false,
      // 直到迭代器结束done才是true。
      // next.value是一个["key","value"]的数组,是返回的迭代器中的元素值。
    

    实例3:iterator.next方法运行

      var arr = ["a", "b", "c"];
      var iter = arr.entries();
      var a = [];
    
      // for(var i=0; i< arr.length; i++){   // 实际使用的是这个 
      for(var i=0; i< arr.length+1; i++){    // 注意,是length+1,比数组的长度大
          var tem = iter.next();             // 每次迭代时更新next
          console.log(tem.done);             // 这里可以看到更新后的done都是false
          if(tem.done !== true){             // 遍历迭代器结束done才是true
              console.log(tem.value);
              a[i]=tem.value;
          }
      }
          
      console.log(a);                         // 遍历完毕,输出next.value的数组
    
    结果:
      false
      [0, "a"]
      false
      [1, "b"]
      false
      [2, "c"]
      true
      (3) [Array(2), Array(2), Array(2)]
      0: (2) [0, "a"]
      1: (2) [1, "b"]
      2: (2) [2, "c"]
        length: 3
      __proto__: Array(0)
    

    实例4:二维数组按行排序

    function sortArr(arr) {
        var goNext = true;
        var entries = arr.entries();
        while (goNext) {
            var result = entries.next();
            if (result.done !== true) {
                result.value[1].sort((a, b) => a - b);
                goNext = true;
            } else {
                goNext = false;
            }
        }
        return arr;
    }
    
    var arr = [[1,34],[456,2,3,44,234],[4567,1,4,5,6],[34,78,23,1]];
    sortArr(arr);
    
    /*(4) [Array(2), Array(5), Array(5), Array(4)]
        0:(2) [1, 34]
        1:(5) [2, 3, 44, 234, 456]
        2:(5) [1, 4, 5, 6, 4567]
        3:(4) [1, 23, 34, 78]
        length:4
        __proto__:Array(0)
    */
    

    实例5:使用 for…of 循环

    var arr = ["a", "b", "c"];
    var iterator = arr.entries();
    // undefined
    
    for (let e of iterator) {
        console.log(e);
    }
    
    // [0, "a"] 
    // [1, "b"] 
    // [2, "c"]
    
    4、every() 的使用

       测试一个数组内的所有元素是否都能通过某个指定函数的测试,返回一个布尔值;
    注意:若收到一个空数组,此方法在一切情况下都会返回 true

    语法:arr.every(callback[, thisArg])

    参数:
      |---callback:用来测试每个元素的函数,它可以接收三个参数:
         |--- currentValue: 用于测试的当前值;
         |--- index: 可选,用于测试的当前值的索引;
         |--- array: 可选,调用 every 的当前数组;
      |---thisArg:执行 callback 时使用的 this 值;

    返回值:
      |---如果回调函数的每一次返回都为 truthy 值,返回 true ,否则返回 false。

    说明:
    every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
    every() 方法使用指定函数检测数组中的所有元素:

    • 如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
    • 如果所有元素都满足条件,则返回 true。

    注意: every() 不会对空数组进行检测。
    注意: every() 不会改变原始数组。

    实例1:检测所有数组元素的大小

      //检测数组中的所有元素是否都大于 10
      function isBigEnough(currentValue, index, array) {
        return element >= 10;
      }
      [12, 5, 8, 130, 44].every(isBigEnough);   // false
      [12, 54, 18, 130, 44].every(isBigEnough); // true
    

    实例2:使用箭头函数

      [12, 5, 8, 130, 44].every(x => x >= 10); // false
      [12, 54, 18, 130, 44].every(x => x >= 10); // true
    
    5、fill() 的使用

       用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引;

    语法:arr.fill(value[, start[, end]])

    参数:
      |---value:用来填充数组元素的值;
      |---start:可选,起始索引,默认值为0;
      |---end:可选,终止索引,默认值为 this.length;

    返回值:
      |--- 修改后的数组。

    实例1:

      [1, 2, 3].fill(4);               // [4, 4, 4]
      [1, 2, 3].fill(4, 1);            // [1, 4, 4]
      [1, 2, 3].fill(4, 1, 2);         // [1, 4, 3]
      [1, 2, 3].fill(4, 1, 1);         // [1, 2, 3]
      [1, 2, 3].fill(4, 3, 3);         // [1, 2, 3]
      [1, 2, 3].fill(4, -3, -2);       // [4, 2, 3]
      [1, 2, 3].fill(4, NaN, NaN);     // [1, 2, 3]
      [1, 2, 3].fill(4, 3, 5);         // [1, 2, 3]
      Array(3).fill(4);                // [4, 4, 4]
      [].fill.call({ length: 3 }, 4);  // {0: 4, 1: 4, 2: 4, length: 3}
      
      // Objects by reference.
      var arr = Array(3).fill({}) // [{}, {}, {}];
      arr[0].hi = "hi"; // [{ hi: "hi" }, { hi: "hi" }, { hi: "hi" }]
    
    6、filter() 的使用

       filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素

    语法:var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])

    参数:
      |---callback:用来测试每个元素的函数,它可以接收三个参数:
         |--- currentValue:数组中当前正在处理的值;
         |--- index: 可选,正在处理的元素在数组中的索引;
         |--- array: 可选,调用了 filter 的数组本身;
      |---thisArg:可选,执行 callback 时,用于 this 的值;

    返回值:
      |---一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组。

    实例1:筛选排除所有较小的值

     function isBigEnough(element) {
          return element >= 10;
      }
     var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
      //  [12, 130, 44]
    
     //回调函数箭头函数写法
     var filtered2 = [12, 5, 8, 130, 44].filter((element)=> element >= 10);
     //  [12, 130, 44]
    

    实例2:过滤 JSON 中的无效条目

         //使用 filter() 创建具有非零 id 的元素的 json
            var arr = [
                { id: 15 },
                { id: -1 },
                { id: 0 },
                { id: 3 },
                { id: 12.2 },
                { },
                { id: null },
                { id: NaN },
                { id: 'undefined' }
            ];
    
            var invalidEntries = 0;
    
            function isNumber(obj) {
                return obj !== undefined && typeof(obj) === 'number' && !isNaN(obj);
            }
    
            function filterByID(item) {
                if (isNumber(item.id) && item.id !== 0) {
                    return true;
                }
                invalidEntries++;
                return false;
            }
    
            var arrByID = arr.filter(filterByID);
    
            console.log('过滤后的数组:\n', arrByID);
            // Filtered Array
            // [{ id: 15 }, { id: -1 }, { id: 3 }, { id: 12.2 }]
    
            console.log('无效的条目数 = ', invalidEntries);
            // 无效的条目数  = 5
    /*******************************************************************************************/
       //用箭头函数简化代码,如下
            var invalidEntries2 = 0;
            var arrByID2 = arr.filter((item) =>
                item.id !== undefined && typeof(item.id ) === 'number' && !isNaN(item.id ) && item.id !== 0 ?
                true : (invalidEntries2++,false)
            );
            console.log('\n过滤后的数组2:\n', arrByID2);
            // Filtered Array
            // [{ id: 15 }, { id: -1 }, { id: 3 }, { id: 12.2 }]
    
            console.log('无效的条目数2 = ', invalidEntries2);
            // 无效的条目数  = 5
    

    实例3:在数组中搜索

          //使用 filter() 根据搜索条件来过滤数组内容
            var fruits = ['apple', 'banana', 'grapes', 'mango', 'orange'];
    
            /**
             * Array filters items based on search criteria (query)
             */
            function filterItems(query) {
                return fruits.filter(function(el) {
                    return el.toLowerCase().indexOf(query.toLowerCase()) > -1;
                })
            }
            console.log(filterItems('ap')); // ['apple', 'grapes']
            console.log(filterItems('an')); // ['banana', 'mango', 'orange']
    
     /*************************************************************************************/
            //箭头函数写法
            const filterItems2 = (query) => {
                return fruits.filter((el) =>
                    el.toLowerCase().indexOf(query.toLowerCase()) > -1
                );
            }
            console.log(filterItems2('ap')); // ['apple', 'grapes']
            console.log(filterItems2('an')); // ['banana', 'mango', 'orange']
    
    7、find() 的使用

       find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined

    语法:arr.find(callback[, thisArg])

    参数:
      |--- callback:在数组每一项上执行的函数,接收 3 个参数:
         |--- currentValue:当前遍历到的元素;
         |--- index: 可选,当前遍历到的索引;
         |--- array: 可选,数组本身;
      |---thisArg:执行回调时用作this 的对象;

    返回值:
      |--- 数组中第一个满足所提供测试函数的元素的值,否则返回 undefined。

    实例1:用对象的属性查找数组里的对象

           var inventory = [
                {name: 'apples', quantity: 2},
                {name: 'bananas', quantity: 0},
                {name: 'cherries', quantity: 5}
            ];
    
            function findCherries(fruit) {
                return fruit.name === 'cherries';
            }
            console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }
    
    /********************************************************************************/
            //箭头函数简化写法
            console.log(inventory.find((fruit)=>fruit.name === 'cherries'));
    

    实例2:寻找数组中的质数

    //如何从一个数组中寻找质数(如果找不到质数则返回undefined)
          function isPrime(element, index, array) {
               var start = 2;
               while (start <= Math.sqrt(element)) {
                   if (element % start++ < 1) {
                        return false;
                   }
                }
                return element > 1;
            }
    
            console.log([4, 6, 8, 12].find(isPrime)); // undefined, not found
            console.log([4, 5, 8, 12].find(isPrime)); // 5
     /*****************************************************************************/
            console.log([4, 5, 8, 12].find((item)=>{
                var st = 2;
                while (st <= Math.sqrt(item)){
                    if (item % st++ < 1) {
                        return false;
                    }
                }
                return item > 1;
            })); // 5
    
    8、findIndex() 的使用

      findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1

    语法:arr.findIndex(callback[, thisArg])

    参数:
      |--- callback:针对数组中的每个元素, 都会执行该回调函数, 执行时会自动传入下面三个参数:
         |--- currentValue:当前的元素;
         |--- index: 当前元素的索引;
         |--- array: 调用findIndex的数组;
      |---thisArg:可选。执行callback时作为this对象的值;

    实例1:查找数组中首个质数元素的索引

          //查找数组中素数的元素的索引(如果不存在素数,则返回-1)。
            function isPrime(element, index, array) {
                var start = 2;
                while (start <= Math.sqrt(element)) {
                    if (element % start++ < 1) {
                        return false;
                    }
                }
                return element > 1;
            }
    
            console.log([4, 6, 8, 12].findIndex(isPrime)); // -1, not found
            console.log([4, 6, 7, 12].findIndex(isPrime)); // 2
    
    9、flat() 的使用

       按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回;

    语法:var newArray = arr.flat(depth)

    参数:
      |--- depth:可选。指定要提取嵌套数组的结构深度,默认值为 1

    返回值:
      |--- 一个包含将数组与子数组中所有元素的新数组。

    实例1:扁平化嵌套数组

      var arr1 = [1, 2, [3, 4]];
      arr1.flat(); 
      // [1, 2, 3, 4]
    
      var arr2 = [1, 2, [3, 4, [5, 6]]];
      arr2.flat();
      // [1, 2, 3, 4, [5, 6]]
    
      var arr3 = [1, 2, [3, 4, [5, 6]]];
      arr3.flat(2);
      // [1, 2, 3, 4, 5, 6]
    
      //使用 Infinity 作为深度,展开任意深度的嵌套数组
      arr3.flat(Infinity); 
      // [1, 2, 3, 4, 5, 6]
    

    实例2:扁平化嵌套数组

      //flat() 方法会移除数组中的空项
      var arr4 = [1, 2, , 4, 5];
      arr4.flat();
      // [1, 2, 4, 5]
    

    替代方案
    实例3:使用 reduce 与 concat 替代

      var arr = [1, 2, [3, 4]]; 
      console.log(arr.flat()); // [1, 2, 3, 4]
    
      // 反嵌套一层数组
      var  newArr = arr.reduce((acc, val) => acc.concat(val), []); 
      console.log(newArr); // [1, 2, 3, 4]
    
      // 或使用 ...
      console.log( [].concat(...arr) );  // [1, 2, 3, 4]
    
      // 使用 reduce、concat 和递归无限反嵌套多层嵌套的数组
      var arr = [1,2,3,[1,2,3,4, [2,3,4]]];
    
      //使用flat
      console.log(arr.flat(Infinity)); // [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
    
      //使用reduce 和 concat
      function flattenDeep(arr) {
          return arr.reduce((acc, val) => Array.isArray(val) ? 
              acc.concat(flattenDeep(val)) : acc.concat(val), []);
      }
      console.log(flattenDeep(arr)); // [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
    
    10、flatMap() 的使用

       首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 以及 深度值为1的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些;

    语法:var new_array = arr.flatMap(function callback(currentValue[, index[, array]]) {
          // 返回新数组的元素
         }[, thisArg])

    参数:
      |--- callback:可以生成一个新数组中的元素的函数,可以传入三个参数:
         |--- currentValue:当前正在数组中处理的元素;
         |--- index: 可选的。数组中正在处理的当前元素的索引;
         |--- array: 可选的。被调用的 map 数组;
      |---thisArg:可选的。执行 callback 函数时 使用的this 值;

    返回值:
      |--- 一个新的数组,其中每个元素都是回调函数的结果,并且结构深度 depth 值为1。

    实例1:Map 与 flatMap

      var arr1 = [1, 2, 3, 4];
    
      arr1.map(x => [x * 2]); 
      // [[2], [4], [6], [8]]
    
      arr1.flatMap(x => [x * 2]);
      // [2, 4, 6, 8]
    
      // 只会将 flatMap 中的函数返回的数组 “压平” 一层
      arr1.flatMap(x => [[x * 2]]);
      // [[2], [4], [6], [8]]
    

      虽然上面的代码使用 map 和 flatMap 好像都可以,但这只能展示如何使用 flatMap。

      所以,为了更好的展示 flatMap 的作用,下面我们将包含几句话的数组拆分成单个汉字组成的新数组。

      let arr = ["今天天气不错", "", "早上好"]
    
      arr.map(s => s.split(""))
      // [["今", "天", "天", "气", "不", "错"],[""],["早", "上", "好"]]
      
      arr.flatMap(s => s.split(''));
      // ["今", "天", "天", "气", "不", "错", "早", "上", "好"]
    

    等价操作:

      //使用 reduce 与 concat
      var arr1 = [1, 2, 3, 4];
    
      arr1.flatMap(x => [x * 2]);
      // 等价于
      arr1.reduce((acc, x) => acc.concat([x * 2]), []);
      // [2, 4, 6, 8]
    

    后文,继续......

    相关文章

      网友评论

          本文标题:JS Array 对象——(1)

          本文链接:https://www.haomeiwen.com/subject/lqmujctx.html