JavaScript里的数组详解

前言:这篇文章用于了解总结JS里的数组的相关知识。我会从基本概念,构造方法和常用的API这几个方面来介绍数组。部分概念与代码摘自阮一峰JS教程

1、数组是什么

数组(array)是按次序排列的一组值。每个值的位置都有编号(从0开始),整个数组用方括号表示。

其实本质上,数组属于一种特殊的对象。typeof运算符会返回数组的类型是object。
数组的特殊性体现在,它的键名是按次序排列的一组整数(0,1,2…)。而由于数组成员的键名是固定的(默认总是0、1、2…),因此数组不用为每个元素指定键名,而对象的每个成员都必须指定键名。

2、数组的length属性

数组的length属性,返回数组的成员数量。只要是数组,就一定有length属性。该属性是一个动态的值,等于键名中的最大整数加上1。

3、数组的构造方法

  • var x = new Array(3) ; // 3表示数组的长度,每一项都为undefined
  • var y = new Array(3,3); // 此时得到一个数组[3,3] ,即里面的两个参数表示数组的第0项和第1项

上面两行代码展示了JS的不一致行,即不同的参数个数,导致相同位置的参数所表示的意义是不同的。
使用new Array()的构造方法,是仿自Java中的写法,不常用。

因此,其实众所周知的函数构造方法是直接定义,如:
var a = [3,3] ; // 得到了一个数组a,其中第0项和第一项分别为3、3

4、in 运算符 && for…in 循环

检查某个键名是否存在的运算符in,适用于对象,也适用于数组。
因此,数组也是可以使用for in循环的,for…in循环不仅可以遍历对象,也可以遍历数组,毕竟数组只是一种特殊对象。
如:

var a = [1, 2, 3];

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

但是,for…in不仅会遍历数组所有的数字键,还会遍历非数字键。因此不建议使用。

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

for (var key in a) {
  console.log(key);
}
// 0
// 1
// 2
// foo

5、数组的遍历

上面讲了使用for…in来遍历数组,但是不建议使用,我们常用的数组遍历方法有for循环或while循环

如:

var a = [1, 2, 3];

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

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

var l = a.length;
while (l--) {
  console.log(a[l]);
}

6、数组的空位

当数组的某个位置是空元素,即两个逗号之间没有任何值,我们称该数组存在空位(hole),下面代码表明,数组的空位不影响length属性。
如:var a = [1, , 1]; a.length // 3
数组的空位是可以读取的,返回undefined。
使用delete命令删除一个数组成员,会形成空位,并且不会影响length属性。如:

var a = [1, 2, 3];
delete a[1];

a[1] // undefined
a.length // 3

注:数组的某个位置是空位,与某个位置是undefined,是不一样的。如果是空位,使用数组的forEach方法、for…in结构、以及Object.keys方法进行遍历,空位都会被跳过,如果某个位置是undefined,遍历的时候就不会被跳过。
如:

// 数组中有空位时
var a = [, , ,];

a.forEach(function (x, i) {
  console.log(i + '. ' + x);
})
// 不产生任何输出

for (var i in a) {
  console.log(i);
}
// 不产生任何输出

Object.keys(a)
// []

//数组中的值为undefined时
var a = [undefined, undefined, undefined];

a.forEach(function (x, i) {
  console.log(i + '. ' + x);
});
// 0. undefined
// 1. undefined
// 2. undefined

for (var i in a) {
  console.log(i);
}
// 0
// 1
// 2

Object.keys(a)
// ['0', '1', '2']

这就是说,空位就是数组没有这个元素,所以不会被遍历到,而undefined则表示数组有这个元素,值是undefined,所以遍历不会跳过。

7、类数组对象

如果一个对象的所有键名都是正整数或零,并且有length属性,那么这个对象就很像数组,语法上称为“类似数组的对象”(array-like object)。
典型的“类似数组的对象”是函数的arguments对象,以及大多数 DOM 元素集,还有字符串。

**数组与类数组对象最本质的区别为:类数组对象的原型链中没有Array.prototype,即:
数组.__proto__ === Array.protype
类数组对象.__proto__ === Object.prototype**

因此产生了一句很神奇的话:数组之所以是数组不是因为它本身是数组,而是因为你认为它是数组所以它才是数组。

8、数组的各种API

  • forEach() 遍历
    不支持breakcontinue
    代码示例:
array = ['a','b','c','d'] ;
array.forEach(function(value,key){
  console.log(key+':'+value);
})
// 0:a
// 1:b
// 2:c
// 3:d

其中:使用forEach循环遍历,原数组不会被改变,没有返回值

  • sort() 排序
    该方法是JS封装的一个重排序方法,使用的算法是“快速排序”。不传参时默认为升序排列。注:sort()方法返回的是原数组,即使用该方法会改变原来的数组序列
    =>arr.sort(function(a,b){return a-b}) 升序
    =>arr.sort(function(a,b){return b-a}) 降序
    上面两行代码中,为什么return a-b会升序排列,return b-a会降序排列呢?
    原理如下:

    函数返回值 小于等于 -1 时,a在前,b在后
    函数返回值 在区间(-1,1)时,序列不变
    函数的返回值 大于等于 1 时 ,b在前,a在后

  • join() 分隔
    该方法返回的是字符串,参数表示用什么分隔数组的每一项,不传参默认逗号分隔,参数为空数组时,数组每一项之间没有间隔。
    代码示例:

array = ["a", "b", "c", "d"];
array.join('-');
// "a-b-c-d"
  • concat() 连接
    该方法返回的是新数组,原数组不会被改变。
    代码示例:
a = [1,2,30] ;
b = [42,22,33];
a.concat(b);
// 得到新数组 [1, 2, 30, 42, 22, 33]

使用concat()方法可以用于复制数组,如:

arr = [1,2,3,4,5,6];
var newArr = arr.concat([]);
// newArr 的值为 [1, 2, 3, 4, 5, 6]
newArr === arr; // false

注:关于newArr === arr返回的是false,因为数组也是对象,所以参照对象的相等可得,newArr 和 arr 是两个不同地址的引用,只是恰好他们引用的地址中的值是一样的而已,而两个对象本身的值肯定是不同的。

  • map()
    功能与forEach相同,但map()有返回值。同样不会改变原数组的值,返回的一个新数组。
    代码示例:
arr = [1, 2, 3, 4, 5, 6];
arr.map(function(value,key){
    return value * 2;
})
// [2, 4, 6, 8, 10, 12]
  • filter() 过滤、筛选
    用法与map()一样,代码示例:
arr = [1, 2, 3, 4, 5, 6];
arr.filter(function(value,key){
    return value > 3
})
// [4, 5, 6]
  • reduce() 可接收一个函数作为累加器
    代码示例:计算数组中每一项相加的值
arr = [1, 2, 3, 4, 5, 6];
arr.reduce(function(previous,current){
    return previous + current;
},0)
// 21

reduce()方法,第一个参数传一个函数作为累加器,第二个参数表示初始值。

可以用reduce()方法来写map()数组每一项×2:

a = [1, 2, 3, 4, 5, 6];
a.reduce(function(array,n){
    array.push(n * 2);
    return array;
},[])
// [2, 4, 6, 8, 10, 12]

可以用reduce()方法来写filter()筛选偶数:

a = [1, 2, 3, 4, 5, 6];
a.reduce(function(array,n){
    if(n % 2 === 0){
            array.push(n);
        }
    return array;
},[])
// [2, 4, 6]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值