数组是什么?
数组本质上属于一种特殊的对象,我们可以理解为按次序排列的一组值,每个位置都有对应的索引,索引从0开始。
数组的length属性
数组的length
属性,返回数组的成员数量,length属性的值是动态的,它的值为数组的最大索引数+1。
var arr = [10,20,30];
arr.length; //3 arr[100] = 11111; arr.length //101
如果要把数组清空,将length属性设置为0就可以了
arr.length = 0 arr //[] 数组里的元素被清空了
数组的创建
数组有两种创建的方式:
1)用Array的方法构造函数(不建议使用)
var arr = new Array(3) undefined arr (3) [empty × 3]
用这方法创建数组会带来很多问题,因为给的参数不同,给出的结果也不一致,一般都不建议使用这种方式。
2)字面量的方式定义数组
var arr = [100,'我是数组中的一员','我是索引为2的值'] undefined arr (3) [100, "我是数组中的一员", "我是索引为2的值"] 0: 100 1: "我是数组中的一员" 2: "我是索引为2的值" length: 3 __proto__: Array(0)
像这样数组用中括号括起来,数组里的成员之间用逗号分割,一般都是用这种方法。
数组常用方法
较为简单的方法:
Array.isArray()
Array.isArray()方法可以判断是不是数组对象。
var arr = ['a','b',3]; Array.isArray(arr) // true
instanceof运算符也可以判断是否是数组
var arr = ['a','b',3]; arr instanceof Array //true
push() 、 pop()
push()向数组的末尾添加元素,返回添加成功后的数组的长度,会改变原数组。
var arr = ['a','b']; arr.push('c'); arr //(3) ["a", "b", "c"]
pop()删除数组的最后一个元素,并返回删除的这个元素,会改变原数组。
arr //["a", "b", "c"] arr.pop() //"c" arr //["a", "b"]
这里需要注意,pop()方法如果对空数组使用,不会报错,返回的是undefined。
[].pop() // undefined
unshift() 、 shift()
unshift()在数组的第一个位置添加元素,并返回添加新元素后的数组长度。
var arr = ['b','c']; arr.unshift('a'); arr // (3) ["a", "b", "c"]
这方法会改变原数组
shift()删除数组的第一个元素,并返回删除的那个元素
arr // ["a", "b", "c"] arr.shifit() // "a" arr // ["b", "c"]
这方法和unshift()相反,但是也是会改变原数组
join()
join()方法以指定参数作为分隔符,将所有数组成员连接为一个字符串返回。
var arr = [5,6,7,8] arr.join('-') // "5-6-7-8" arr.join('/') // "5/6/7/8"
如果不提供参数,默认用逗号分隔。
arr // [5, 6, 7, 8] arr.join() //5,6,7,8"
如果数组成员是undefined
或null
或空位,会被转成空字符串。
[undefined,null].join('-') // "-" ['a',,'b'].join('-') //"a--b"
这里提及一下空位,空位是数组中中有索引但是却没有值的意思,['a',,'b']中 元素a和b之间没有任何元素,中间那个就是空位。
空位是可以读取的,而且被计入到数组长度中,但是读取的值为undefined。
var arr = ['a',,'b']; arr[1] // undefined
用delete命令可以删除数组中的某个元素,被删除的那个元素的索引位置就会产生一个空位。
var arr = [1,2,3] delete arr[0] // true arr.length //3 arr //(3) [empty, 2, 3]
用delete命令删除后返回true,数组长度还是不变,所以要清空数组的元素不能用delete,只能将length属性设为0。
数组中某个元素的值为undefined与某位置是空位是不一样的。
如果数组中某元素的值为undefined,在使用数组中的某些方法(如map()、forEach())、for...in结构、Object.keys方法遍历,不会被跳过;而当数组中某位置是空位是会被跳过的。
concat()
concat()方法将多个数组进行合并
var arr = [1,2,3]; var arr2 = [4,5,6]; arr.concat(arr2) //(6) [1, 2, 3, 4, 5, 6]
它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变。
reverse()
reverse()方法用于颠倒排列数组元素,返回改变后的数组。
var arr = [1,2,3,4,5,6,7,8,9,10]; arr.reverse() // (10) [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
会改变原数组
slice()
slice()方法用于提取目标数组的一部分,返回一个新数组,原数组不变。
该方法有2个参数,第一个参数是起始的索引位置,第二个是结束的索引位置(但是不包括此索引),如果没有第二个参数,则会提取由第一个参数所在的索引位置往后至最后一个成员。
var arr = ['a','b','c','d'] arr.slice(1,3) // (2) ["b", "c"] arr.slice(2) // (2) ["c", "d"]
如果传入的参数为负数,则提取的位置是从后面开始
arr // ['a','b','c','d'] arr.slice(-2) // (2) ["c", "d"]
indexOf() 、 lastIndexOf()
indexOf()方法返回括号里面元素在数组中第一次出现的索引位置。
['a','b','c','d'].indexOf('b') // 1
如果没有则会返回-1。
['a','b','c','d'].indexOf('e') // -1
该方法可以传入第二个参数,表示从某个索引位置开始查找。
[1,2,3,2,3].indexOf(2,1) // 1 [1,2,3,2,3].indexOf(1,1) // -1
lastIndexOf()则是返回括号元素在数组中最后一次出现的索引位置,如果没有返回-1。
[1,2,3,2,3].lastIndexOf(3) // 4
注意,这两个方法不能用来搜索NaN
的位置,即它们无法确定数组成员是否包含NaN,因为这两个方法内部用的是严格相等运算符(===)进行比较,NaN是不等于自身的。
[NaN,'a','b','c'].indexOf(NaN) // -1 [NaN,'a','b','c'].lastIndexOf(NaN) // -1
常见的复杂方法(参数是另一个函数)
sort()
sort()方法对数组成员进行排序,默认是按照字典顺序排序。排序后,会改变元数组。sort()方法内部使用的是快速排序的算法。
['a','d','f','j','b','c'].sort() // ["a", "b", "c", "d", "f", "j"]
这方法不是按照比大小的方式在排序的,默认排序顺序是根据字符串Unicode码点。
一般我们不希望用到默认的排序方法,sort()可以将函数作为参数传入,我们可以自己自定义排序方法
[10111, 1101, 111].sort(function (a, b) { return a - b; }) // [111, 1101, 10111]
上面代码中,sort
的参数函数本身接受两个参数,表示进行比较的两个数组成员。如果该函数的返回值大于0
,表示第一个成员排在第二个成员后面;其他情况下,都是第一个元素排在第二个元素前面。
splice()
splice()删除原数组的一部分成员,返回被删的元素。该方法可以对数组添加元素,也可以删除部分元素
var arr = ['a','b','c','d',1,3,2] arr.splice(4,3) // [1, 3, 2] arr // ["a", "b", "c", "d"]
splice()方法可以传入3个参数,第一个参数为被操作起始位置,第二个参数是操作的元素个数,第三个参数是添加的元素,如果省略则是不添加。上面代码表示是
从索引位置4开始往后删除3个元素,返回的是被删除的元素。
如果不想删除元素,只想添加元素,那么第二个参数设为0
var arr = ['a',1,2,3]; arr.splice(1,0,'b','c') // [] // 从下标为0开始,删除0个元素,并添加元素b和c arr //(6) ["a", "b", "c", 1, 2, 3]
如果只提供第一个参数,等同于将原数组在指定位置拆分成两个数组。
var a = [1,2,3,4,5,6] a.splice(3) // [4, 5, 6] a // [1, 2, 3]
该方法会改变原数组。
map()
map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。不影响原数组。
var numbers = [1,2,3,4] numbers.map(function(n){ return n*n; }) // [1, 4, 9, 16] numbers // [1, 2, 3, 4]
map()
方法接受一个函数作为参数。该函数调用时,map
方法向它传入三个参数:当前成员、当前位置和数组本身。一般第三个参数可以省略。
[1, 2, 3].map(function(elem, index, arr) { return elem * index; }); // [0, 2, 6]
上面代码中,map
方法的回调函数有三个参数,elem
为当前成员的值,index
为当前成员的位置,arr
为原数组([1, 2, 3]
)。
map()
方法还可以接受第二个参数,用来绑定回调函数内部的this
变量。
forEach()
该方法和map()很像,都是对数组的所有成员依次执行参数函数。但是,forEach
方法不返回值,主要是用来操作数据的。
和map()一样该方法传入一个函数作为参数,该函数同样接受三个参数:当前值、当前位置、整个数组。
var numbers = [1,2,3,4] numbers.forEach(function(element, index){ console.log('我是'+element+'下标的值为'+index) }) // 我是1下标的值为0 // 我是2下标的值为1 // 我是3下标的值为2 // 我是4下标的值为3
forEach
方法也可以接受第二个参数,绑定参数函数的this
变量。
filter()
filter()方法用于过滤数组,返回的值为符合条件的新数组。通俗理解就是过滤器。
var numbers = [-4,-3,0,3,7] numbers.filter(function(n){ return n > 0; }) // [3, 7] numbers // [-4, -3, 0, 3, 7]
该方法的参数函数也是接受三个参数:当前成员,当前位置和整个数组。
some() 、 every()
这两个方法用来判断数组的成员是否满足某个条件,返回的值是布尔值。
它们接受一个函数作为参数,所有数组成员依次执行该函数。该函数接受三个参数:当前成员、当前位置和整个数组,然后返回一个布尔值。
some
方法是只要一个成员的返回值是true
,则整个some
方法的返回值就是true
,否则返回false
。
[-5,-8,-2,-10,2].some(function(n){ return n > 0; }) //true
every
方法是所有成员的返回值都是true
,整个every
方法才返回true
,否则返回false
。
[-5,-8,-2,-10,2].every(function(n){ return n < 0; }) // false