JavaScript:数组

Posted qianmo39

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript:数组相关的知识,希望对你有一定的参考价值。

1、创建数组

// 推荐使用
var arr = [1, ,2 ,3];

// 不推荐使用
var arr = new Array(1, 2);

2、数组的本质

本质上,数组属于一种特殊的对象。

typeof[1, 2, 3] // "Object"

数组的特殊性体现在,它的键名是按次序排列的一组整数(0,1,2...)。

var arr = [1, 2, 3];

Object.keys(arr) // ?["0", "1", "2"]

3、数组的遍历

var arr = [1, 2, 3];
a.foo = true;

// for...in
for (var i in arr) {
    console.log(arr[i]); // 1 2 3 true
}

// for循环
for (var i = 0; i < arr.length; i++) {
    console.log(arr[i]); // 1 2 3
}

// while循环
var i = 0; 
while(i < a.length) {
    console.log(arr[i]); // 1 2 3
    i++;
}

// forEach
arr.forEach(function (i) {
    console.log(i); // 1 2 3
});

使用for...in不仅会遍历数组所有的数字键,还会遍历非数字键。所以,不推荐使用for...in遍历数组。

4、类似数组的对象

如果一个对象的所有键名都是正整数或零,并且有length属性,那么这个对象就很像数组,语法上称为“类似数组的对象”(array-like object)。

  • arguments对象

    function args() { return arguments }
    var arrayLike = args(‘a‘, ‘b‘);
    
    arrayLike[0] // ‘a‘
    arrayLike.length // 2
    arrayLike instanceof Array // false
    
  • DOM元素集

    var elts = document.getElementsByTagName(‘h3‘);
    elts.length // 3
    elts instanceof Array // false
    
  • 字符串

    ‘abc‘[1] // ‘b‘
    ‘abc‘.length // 3
    ‘abc‘ instanceof Array // false
    

5、构造函数

// 无参数时,返回一个空数组
new Array() // []

// 单个正整数参数,表示返回的新数组的长度
new Array(1) // [ empty ]
new Array(2) // [ empty x 2 ]

// 非正整数的数值作为参数,会报错
new Array(3.2) // RangeError: Invalid array length
new Array(-3) // RangeError: Invalid array length

// 单个非数值(比如字符串、布尔值、对象等)作为参数,
// 则该参数是返回的新数组的成员
new Array(‘abc‘) // [‘abc‘]
new Array([1]) // [Array[1]]

// 多参数时,所有参数都是返回的新数组的成员
new Array(1, 2) // [1, 2]
new Array(‘a‘, ‘b‘, ‘c‘) // [‘a‘, ‘b‘, ‘c‘]

注意,如果参数是一个正整数,返回数组的成员都是空位。虽然读取的时候返回undefined,但实际上该位置没有任何值。虽然这时可以读取到length属性,但是取不到键名。

var a = new Array(3);
var b = [undefined, undefined, undefined];

a.length // 3
b.length // 3

a[0] // undefined
b[0] // undefined

0 in a // false
0 in b // true

6、方法

  • Array.isArray():用来判断某个变量是否是一个数组对象。

    var arr = [1, 2, 3];
    
    typeof arr // "object"
    Array.isArray(arr) // true
    
  • valueOf():返回数组本身。

    Array.valueOf === Object.prototype.valueOf // true
    
    var arr = [1, 2, 3];
    arr.valueOf() // [1, 2, 3]
    
  • toString():返回数组的字符串形式。

    Array.toString === Function.prototype.toString // true
    
    var arr = [1, 2, 3];
    arr.toString() // "1,2,3"
    
    var arr = [1, 2, 3, [4, 5, 6]];
    arr.toString() // "1,2,3,4,5,6"
    
  • push():在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。

    var arr = [];
    
    arr.push(1) // 1
    arr.push(‘a‘) // 2
    arr.push(true, {}) // 4
    arr // [1, ‘a‘, true, {}]
    
  • pop():删除数组的最后一个元素,并返回该元素。注意,该方法会改变原数组。

    var arr = [‘a‘, ‘b‘, ‘c‘];
    
    arr.pop() // ‘c‘
    arr // [‘a‘, ‘b‘]
    
    [].pop() // undefined
    
  • shift():删除数组的第一个元素,并返回该元素。注意,该方法会改变原数组。

    var a = [‘a‘, ‘b‘, ‘c‘];
    
    a.shift() // ‘a‘
    a // [‘b‘, ‘c‘]
    
    // 使用shift()遍历数组
    var arr = [1, 2, 3, 4];
    var i;
    
    while(i = arr.shift()) {
        console.log(i); // 1 2 3 4
    }
    
    arr // []
    
  • unshift():在数组的第一个位置添加元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。

    var a = [‘a‘, ‘b‘, ‘c‘];
    
    a.unshift(‘x‘); // 4
    a // [‘x‘, ‘a‘, ‘b‘, ‘c‘]
    
  • join():以指定参数作为分隔符,将所有数组成员连接为一个字符串返回。如果不提供参数,默认用逗号分隔。

    var a = [1, 2, 3, 4];
    
    a.join(‘ ‘) // ‘1 2 3 4‘
    a.join(‘ | ‘) // "1 | 2 | 3 | 4"
    a.join() // "1,2,3,4"
    
    // 如果数组成员是undefined或null或空位,会被转成空字符串。
    [undefined, null].join(‘#‘) // ‘#‘
    
    [‘a‘,, ‘b‘].join(‘-‘) // ‘a--b‘
    
  • concat():用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变。

    [‘hello‘].concat([‘world‘]) // ["hello", "world"]
    [1, 2, 3].concat(4, 5, 6) // [1, 2, 3, 4, 5, 6]
    

    如果数组成员包括对象,concat方法返回当前数组的一个浅拷贝。所谓“浅拷贝”,指的是新数组拷贝的是对象的引用。

    var obj = { a: 1 };
    var oldArray = [obj];
    
    var newArray = oldArray.concat();
    
    obj.a = 2;
    newArray[0].a // 2
    
  • reverse():用于颠倒排列数组元素,返回改变后的数组。注意,该方法将改变原数组。

    var a = [‘a‘, ‘b‘, ‘c‘];
    
    a.reverse() // ["c", "b", "a"]
    a // ["c", "b", "a"]
    
  • slice():用于提取目标数组的一部分,返回一个新数组,原数组不变。

    arr.slice([begin[, end]])
    
    var a = [‘a‘, ‘b‘, ‘c‘];
    // 如果省略第二个参数,则一直返回到原数组的最后一个成员。
    a.slice(0) // ["a", "b", "c"]
    a.slice(1) // ["b", "c"]
    // 包前不包后
    a.slice(1, 2) // ["b"]
    a.slice(2, 6) // ["c"]
    // 如果没有参数,则返回原数组的拷贝。
    a.slice() // ["a", "b", "c"]
    
    // 如果slice()方法的参数是负数,则表示倒数计算的位置。
    var a = [‘a‘, ‘b‘, ‘c‘];
    a.slice(-2) // ["b", "c"]
    a.slice(-2, -1) // ["b"]
    
    // 如果第一个参数大于等于数组长度,或者第二个参数小于第一个参数,则返回空数组。
    var a = [‘a‘, ‘b‘, ‘c‘];
    a.slice(4) // []
    a.slice(2, 1) // []
    

    slice()方法的一个重要应用,是将类似数组的对象转为真正的数组。

    Array.prototype.slice.call({ 0: ‘a‘, 1: ‘b‘, length: 2 }) // [‘a‘, ‘b‘]
    
    Array.prototype.slice.call(document.querySelectorAll("div"));
    Array.prototype.slice.call(arguments);
    
  • splice():用于删除原数组的一部分成员,并可以在删除的位置添加新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组。

    array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
    
    var a = [‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘];
    a.splice(4, 2, 1, 2) // ["e", "f"]
    a // ["a", "b", "c", "d", 1, 2]
    
    // 如果只提供第一个参数,等同于将原数组在指定位置拆分成两个数组。
    var a = [1, 2, 3, 4];
    a.splice(2) // [3, 4]
    a // [1, 2]
    
  • sort():对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变。

    [‘d‘, ‘c‘, ‘b‘, ‘a‘].sort() // [‘a‘, ‘b‘, ‘c‘, ‘d‘]
    [4, 3, 2, 1].sort() // [1, 2, 3, 4]
    [11, 101].sort() // [101, 11]
    [10111, 1101, 111].sort() // [10111, 1101, 111]
    
    // 如果想让sort方法按照自定义方式排序,可以传入一个函数作为参数。
    [10111, 1101, 111].sort(function (a, b) {
      return a - b;
    })
    // [111, 1101, 10111]
    

    注意,自定义的排序函数应该返回数值,否则不同的浏览器可能有不同的实现,不能保证结果都一致。

    // bad
    [1, 4, 2, 6, 0, 6, 2, 6].sort((a, b) => a > b)
    
    // good
    [1, 4, 2, 6, 0, 6, 2, 6].sort((a, b) => a - b)
    
  • map():将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回。

    var new_array = arr.map(function callback(currentValue[, index[, array]]) {
     // Return element for new_array 
    }[, thisArg])
    // 回调函数有三个参数,currentValue为当前成员的值,index为当前成员的位置,array为原数组
    // thisArg用来绑定回调函数内部的this变量
    
  • forEach():对数组的每个元素执行一次给定的函数,没有返回值。

    arr.forEach(function callback(currentValue [, index [, array]])[, thisArg])
    // forEach()的参数与map()相同
    // forEach()不会跳过undefined和null,但会跳过空位。
    
  • filter():用于过滤数组成员,满足条件的成员组成一个新数组返回。

    var newArray = arr.filter(function callback(element[, index[, array]])[, thisArg])
    // 回调函数有三个参数,element为当前成员,index为当前成员的位置,array为原数组
    // thisArg用来绑定回调函数内部的this变量
    
  • some():只要一个成员的返回值是true,则整个some方法的返回值就是true,否则返回false

    arr.some(function callback(element[, index[, array]])[, thisArg])
    // 回调函数有三个参数,element为当前成员,index为当前成员的位置,array为原数组
    // thisArg用来绑定回调函数内部的this变量
    
  • every():所有成员的返回值都是true,整个every方法才返回true,否则返回false

    arr.every(function callback(element[, index[, array]])[, thisArg])
    // 回调函数有三个参数,element为当前成员,index为当前成员的位置,array为原数组
    // thisArg用来绑定回调函数内部的this变量
    
  • reduce():从左到右依次处理数组的每个成员,最终累计为一个值。

    arr.reduce(function callback(accumulator, currentValue[, index[, array]])[, initialValue])
    // accumulator累积变量,currentValue当前变量,index当前位置,array原数组,initialValue累积变量初始值
    
    // 找出字符长度最长的数组成员。
    function findLongest(entries) {
      return entries.reduce(function (longest, entry) {
        return entry.length > longest.length ? entry : longest;
      }, ‘‘);
    }
    
    findLongest([‘aaa‘, ‘bb‘, ‘c‘]) // "aaa"
    
  • reduceRight():从右到左依次处理数组的每个成员,最终累计为一个值。

    arr.reduceRight(function callback(accumulator, currentValue[, index[, array]])[, initialValue])
    // accumulator累积变量,currentValue当前变量,index当前位置,array原数组,initialValue累积变量初始值
    // 在空数组上调用 reduce 或 reduceRight 且未提供初始值会导致类型错误
    
  • indexOf():返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1

    arr.indexOf(searchElement[, fromIndex])
    // searchElement要查找的元素,fromIndex开始查找的位置
    
    [NaN].indexOf(NaN) // -1
    
  • lastIndexOf():返回给定元素在数组中最后一次出现的位置,如果没有出现则返回-1

    arr.lastIndexOf(searchElement[, fromIndex])
    // searchElement要查找的元素,fromIndex开始查找的位置
    
    [NaN].lastIndexOf(NaN) // -1
    
  • 链式使用:上面这些数组方法之中,有不少返回的还是数组,所以可以链式使用。

    var users = [
      {name: ‘tom‘, email: ‘tom@example.com‘},
      {name: ‘peter‘, email: ‘peter@example.com‘}
    ];
    
    users
    .map(function (user) {
      return user.email;
    })
    .filter(function (email) {
      return /^t/.test(email);
    })
    .forEach(function (email) {
      console.log(email);
    });
    // "tom@example.com"
    

    上面代码中,先产生一个所有 Email 地址组成的数组,然后再过滤出以t开头的 Email 地址,最后将它打印出来。

7、参考资料

以上是关于JavaScript:数组的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript单行代码,也就是代码片段

JavaScript 片段

JavaScript 代码片段

10个JavaScript代码片段,使你更加容易前端开发。

10个JavaScript代码片段,使你更加容易前端开发。

几个关于js数组方法reduce的经典片段