JS数组知多少

作者: 人生还有多少个二十年 | 来源:发表于2017-08-19 20:19 被阅读0次

    版权声明:文章首发于本人简书账号人生还有多少个二十年
    欢迎转载,转载请注明出处

    前言

    数组是编程语言中最为常见的数据类型之一,跟对象相比,它的突出特点是“有序”。JS的数组还有一些其它的特点,比如,数组项的类型可以不一致,数组的大小可以动态调整,没有数组下标越界的概念。

    // 一个数组,可以同时包含各种数据类型的数据,而且,数组之中还可以嵌套数组
    var arr = [1, "2", true, null, undefined, [{a:1,b:2,c:3}]];
    arr.length; // 6
    // 不会越界报错,而是在指定索引处创建新元素,并自动更新数组的length属性值。
    arr[100] = 100; 
    arr.length; // 101
    // 数组的length属性是可读可写,把其值调低,则会删除部分元素
    // 调高,则生成稀疏数组
    arr.length = 6;
    arr; // [1, "2", true, null, undefined, [{a:1,b:2,c:3}]]
    arr.length = 10;
    arr[7]; // undefined
    

    数组的常用方法

    接下来,以例子为主,解释为辅,讲解相关知识,欲知详情,请参阅文末“参考资源”

    1. 增删元素(push()、pop()、unshift()、shift())

    var arr = [];
    arr.push("a", "b"); // 2
    arr // ["a", "b"]
    arr.pop(); // "b"
    arr // ["a"]
    arr.unshift("x", "y"); // 3
    arr // ["x", "y", "a"]
    arr.shift(); // "x"
    arr // ["y", "a"]
    
    • push()和unshift()都是向数组添加元素,可以同时添加多个元素,它们的返回值都是更新后的数组的长度;
    • pop()和shift()都是从数组中移除元素,只移除一项,它们的返回值都是被移除的那个元素;
    • push()和pop()的操作发生在数组尾部,unshift()和shift()的操作发生在数组头部;
    • 栈数据结构的访问规则是LIFO(后进先出),插入和删除的操作发生在同一端;而队列的访问规则为FIFO(先进先出),插入和删除的操作不在同一端;
    • push()配合pop()可以模拟栈的行为;shift()和push()、unshift()和pop()都可以实现类似队列的行为。

    2. 重排序(reverse()、sort())

    var arr1 = [1, 2, 3];
    arr1.reverse(); // [3, 2, 1]
    arr1; // [3, 2, 1]
    
    var arr2 = [1, 3, 2];
    arr2.sort(); // [1, 2, 3]
    arr2; // [1, 2, 3]
    
    • 从上面可以看出,reverse()和sort()都会改变原数组,并且它们的返回值都是排序之后的数组。reverse()用于反转数组的顺序。
    • sort()用于以升序或者降序的方式排列数组项。

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

    var arr3 = [1, 2, 10];
    arr3.sort(); // [1, 10, 2]
    var arr4 = ["a", "c", "b", "B"];
    arr4.sort(); // ["B", "a", "b", "c"]
    

    sort()可以接收一个函数,用于提供更实用的排序功能。
    格式如下:sort(fn(arg1, arg2))

    var arr5 = [1, 3, 2];
    // 升序排列
    arr5.sort(function(a, b){
        return a - b;
    }); // [1, 2, 3]
    arr5 //  [1, 2, 3]
    // 降序排列
    arr5.sort(function(a, b){
        return b - a;
    }); // [3, 2, 1]
    

    3. 操作方法(concat()、slice()、splice())

    // concat():用于合并多个数组,生成新数组,对原数组没有影响
    // 数组合并过程中,各数组只拆除最外层的“[]”,合并操作并不是递归的
    // 这表明,生成的新数组仍然可以含有数组
    var arr1 = [];
    arr1.concat([1], [2], [[3,4], [5, 6]]); // [1, 2, [3, 4], [5, 6]];
    arr1; // []
    
    // slice(): 用于截取子数组,且操作并不影响生成的数组
    // 可以给定两个参数,一个是起始索引,一个是结束索引
    var arr2 = ["a", "b", "c", "d"];
    // 没给定参数,相当于复制数组
    arr2.slice(); // ["a", "b", "c", "d"]
    arr2 // ["a", "b", "c", "d"]
    // 只给定起始索引,默认从该索引处一直截取到末尾
    arr2.slice(2); //  ["c", "d"]
    arr2 // ["a", "b", "c", "d"]
    // 记清楚了!从起始索引截取到结束索引之前,并不包含结束索引处的元素
    arr2.slice(1, 3); // ["b", "c"]
    arr2 //  ["a", "b", "c", "d"] 
    
    // splice(): 增、删、替换数组元素,直接修改原数组
    // 该操作的返回值是被删除的元素组成的数组
    var arr3 = ["1", "2", "3", "a", "b", "c"];
    // 从索引为4处开始删除元素,一直到数组末尾
    arr3.splice(4); // ["b", "c"]
    arr3 // ["1", "2", "3", "a"]
    // 从索引为0处开始,删除2个元素
    arr3.splice(0, 2); // ["1", "2"]
    arr3 // ["3", "a"]
    // 从索引为0处开始,删除0个元素,并在该处插入1个元素"x"
    arr3.splice(0, 0, "x"); // []
    arr3 // ["x", "3", "a"]
    // 删除几个元素,就插入几个元素,可以实现splice()替换元素功能
    arr3.splice(0, 1, "y"); // ["x"]
    arr3 // ["y", "3", "a"]
    

    4. 位置方法

    // indexOf()和lastIndexOf()都可以用于查询指定元素在数组中的位置,
    // 返回第一个匹配的元素的索引。
    // 两者的区别在于,前者是从数组头部开始查找,后者则从尾部开始查找
    [1,2,4,-1,2].indexOf(2) // 1
    [1,2,4,-1,2].lastIndexOf(2) // 4
    

    5. 迭代方法(every()、some()、filter()、map()、forEach())

    [1,2,3].every(function(item, index, array){return item > 0;});
    // true
    [1,2,3].every(function(item, index, array){return item > 2;});
    // false
    [1,2,3].some(function(item, index, array){return item > 2;});
    // true
    [1,2,3].filter(function(item, index, array){return item > 2;});
    // [3]
    [1,2,3].map(function(item, index, array){   return item * 2;});
    // [2, 4, 6]
    var sum = 0;
    [1,2,3].forEach(function(item, index, array){sum += item;});
    sum // 6
    

    这五个迭代方法都接收一个函数,并且对数组中的每一项都运行给定函数,这些迭代方法都不会改变原数组。它们的返回值如下:

    • every():给定函数对每一项都返回true,则返回true。
    • some():给定函数对任一项返回true,则返回true。
    • filter():返回该函数会返回true的项组成的数组。
    • map():返回每次函数调用的结果组成的数组。
    • forEach():没有返回值。

    6. 归并方法(reduce()、reduceRight())

    [1,2,3].reduce(function(prev, cur){return prev + cur});
    // 6
    [1,2,3].reduceRight(function(prev, cur){return prev + cur});
    // 6
    

    reduce()和reduceRight()这两个方法都会迭代数组的所有项,然后构建一个最终返回的值。前者的迭代顺序是从前往后,后者则相反

    7. 转换方法(join())

    join()可以将数组转换为字符串,相反,split()可以将字符串转换为数组。
    可以给它们指定分隔符,若未指定,则默认使用逗号。

    var arr = [1,2,3];
    arr.join(); // "1,2,3"
    arr.join(""); // "123"
    arr.join("-"); // "1-2-3"
    arr.join().split(); // ["1,2,3"]
    
    var str = "abc";
    str.split(); // ["abc"]
    str.split(""); // ["a", "b", "c"]
    str.split("-"); // ["abc"]
    str.split().join(); // "abc"
    

    Attentions

    1. 了解各个数组方法的功能,是否有返回值,返回值是什么,是否对原数组造成影响。
    2. 位置方法、迭代方法和归并方法都是ES5的标准。IE兼容性:IE9+。

    参考资源

    • 《JavaScript高级程序设计(第3版)》
    • 《JavaScript权威指南》
    • MDN

    相关文章

      网友评论

        本文标题:JS数组知多少

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