数组的基础结构

  • 数组也是对象数据类型 typeof [] -> ‘object’
  • 数组也是属性名,只不过属性名是数字,我们把数字属性名称之为它的索引:数组是以数字为索引,索引从零开始,有一个length属性代表数组的长度

image.png

类数组:类似于数组,但是不是数组

  • 通过getElementsByTageName 获取的元素集合是类数组
  • 函数中的实参集合argument也是类数组

image.png

1
2
3
4
5
6
7
8
9
10
11
12
// for 循环操作
for(var i =0;i<ary.length;i++){
console.log(ary[i])
}

// for in 循环操作
for(var key in ary){
// key:属性名(数组中的属性名是索引)
console.log(ary[key]);
}

// for 循环只能遍历到数组私有的一些属性,而for in 循环可以吧一些自定义的公共属性也能遍历到

数组中的常用方法

数组中有很多方法

1
console.dir(Array.prototype)
  • 方法的意义和作用
  • 方法的形参
  • 方法的返回值
  • 通过此方法,原来的数组是否发生了改变

实现数组的增加、修改、删除

增加

push : 向数组的末尾追加新内容

参数:一到多个,任何数据类型都可以,想要给数组末尾追加什么,直接传递到push方法中极客,传递多个逗号隔开
返回值:新增后数组的长度
原有数组改变了

unshift:向数组开头追加新内容

参数:需要追加的内容(可以是多个任何数据类型的值)
返回值:新增后 数组的长度
原来数组改变了

把数组当做一个普通的对象,使用对象键值对的操作,给其设置新的属性(索引)
ary[ary.length]=xxx 向数组的末尾追加了新的内容

删除

pop 删除数组最后一项

参数:无
返回值:被删除的那一项内容
原有数组改变了

shift:删除数组第一项

参数:无
返回值:被删除那一项的内容
原有数组改变了
使用shift删除第一项之后,后面每一项的索引都要向前进一位(导致后面项的索引发生了改变)

把数组当做一个普通对象操作
delete删除:delete ary[索引]删除指定索引这一项(当前项被删除后),原有数组其它项的索引不会改变:当前数组的length也不会改变

ary.length–:删除数组最后一项

splice:数组中内置的方法,可以实现数组的增加、修改、删除

splice实现删除
splice(n,m):从索引n开始删除m个(m不写是个删除列数组的末尾,n也不写)
返回值:被删除的内容(以一个新数组保存)
原有数组改变了
splice(0) 清空数组
splice() 一项都不删除,返回一个新的空数组
splice(0,1)删除第一项

splice实现修改

splice(n,m,x):在原有删除的基础上,用x代替删除的内容

splice实现增加
splice(n,0,x):在修改的基础上,我们一项都不删除,把x插入到索引n的前面
ary.splice(0,0,x) 向数组末尾追加新元素

数组的查询

slice 数组的查询

  • 参数:slice(n,m) 从索引n开始找到索引m处(不包含m)
  • 返回值:吧找到的部分已一个新数组返回
  • 原来的数组不变

slice(n) 从索引n开始找到末尾
slice(0) /slice() 数组克隆,克隆一份和原来数组一模一样的的新数组
slice支持负载索引,如果传递的索引为负数,浏览器解析的时候是按照总长度+负数索引 来处理的

将两个数组进行拼接

concat:将多个数组拼接在一起

  • 参数:要拼接的内容(把内容放在原数组的后面),可以是一个数组
  • 返回:拼接后的新数组

原有数组不变
image.png

数组的查询

slice: 数组的查询
参数: slice(n,m) 从索引n开始找到索引为m处(不包含m)
返回值:把找到的部分已一个新数组返回
原来的数组不变

1
2
3
slice(n) 从索引n开始找到末尾
slice(0) / slice() 数组克隆,克隆一份和原来数组一模一样的新数组
slice 支持负数索引,如果传递的索引为负数,浏览器解析的时候是按照,总长度+负数索引 来处理的

数组的拼接

concat:将多个数组拼接在一起
参数:要拼接的内容(把内容放在原数组的后面),可以是一个数组,也可以是一些数据值
返回:拼接后的新数组
原有的数组不变

1
2
let arr = [0,100]
arr.concat([100,200],[200,300],12)

concat() 什么都没有拼接,相当于吧原有数组克隆一份一模一样的出来
image.png

数组转字符串

toString

实现吧数组转化为字符串(转换后的字符串逗号分隔每一项)

参数:无
返回值:转换的字符串
原有数组不变

join

把数组按照指定的分隔符转换为字符串,和字符串中的split相对应

  • 参数:指定的链接符号
  • 返回值:转换后的字符串
  • 原有数组不变

image.png

已知数组的每一项都是数字,想事先数组求和,我们如何实现?

循环实现

1
2
3
4
var total = null;
for(var i=0;i<ary.length;i++){
total+=ary[i];
}

利用join

1
var total = eval(ary.join('+')) // evel:把字符串变为js表达式执行

实现数组中每一项的排序和排列

reverse

把数组中每一项倒过来排序

参数:无
返回值:排序后的数组
原有数组改变

sort

实现数组的排序

参数:无或者回调函数
返回值:排序后的数组
原有数组改变
不传递参数的情况下:可以给10以内的数字进行升序排列,但是超过10的就无法处理(多位数值识别第一位)

1
2
3
4
ary.sort(function(a,b){
return a-b; //升序
return b-a; //降序
})

验证数组中是否包含某一项

indexOf / lastindexOf

获取当前现在数组中第一次或者最后一次出现的位置索引

  • 数组的这两个方法在IE6-IE8下不兼容
  • 字符串的这两个方法兼容所有的浏览器
1
2
3
if(ary.indexOf(12)>-1){
// 数组中包含12
}

原理

1
2
3
4
5
6
7
8
9
10
Array.prototype.myIndexOf = function myIndexOf(value){
var result = -1;
for(var i =0;i<this.length;i++){
if(value===this[i]){
result = i;
break;
}
}
return result;
}

遍历数组每一项的方法

以下方法ie6-8下都不兼容

forEach

遍历数组中的每一项

1
2
3
4
5
ary.forEach(function(value,index){
/* 数组中有多少项,当前回调函数执行多少次,妹妹一次传进来的value就是当前遍历数组这一项的值,index
就是遍历这一项的索引
*/
})

map

遍历数组中的每一项,在forEach的基础上,可以修改每一项的值

1
2
3
4
5
6
7
ary.map(function(value,index){
/* 数组中有多少项,当前回调函数执行多少次,妹妹一次传进来的value就是当前遍历数组这一项的值,index
就是遍历这一项的索引
*/
return xxx;
// return 后面返回的结果就是当前遍历的这一项修改为xxx
})

filter
find
reduce
every

数组去重

var ary = [1,2,3,4,5,6,7,1,3,4,5];

方案一 最简单数组去重法

遍历数组的每一项,拿每一项和它后面的项依次比较,如果相同了,则把相同的这一项在原来数组中删除即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
* 新建一新数组,遍历传入数组,值不在新数组就push进该新数组中
* IE8以下不支持数组的indexOf方法
* */
function uniq(array){
var temp = []; //一个新的临时数组
for(var i = 0; i < array.length; i++){
if(temp.indexOf(array[i]) == -1){
temp.push(array[i]);
}
}
return temp;
}

var aa = [1,2,2,4,9,6,7,5,2,3,5,6,5];
console.log(uniq(aa));

方案二 对象键值法去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
* 速度最快, 占空间最多(空间换时间)
*
* 该方法执行的速度比其他任何方法都快, 就是占用的内存大一些。
* 现思路:新建一js对象以及新数组,遍历传入数组时,判断值是否为js对象的键,
* 不是的话给对象新增该键并放入新数组。
* 注意点:判断是否为js对象键时,会自动对传入的键执行“toString()”,
* 不同的键可能会被误认为一样,例如n[val]-- n[1]、n["1"];
* 解决上述问题还是得调用“indexOf”。*/
function uniq(array){
var temp = {}, r = [], len = array.length, val, type;
for (var i = 0; i < len; i++) {
val = array[i];
type = typeof val;
if (!temp[val]) {
temp[val] = [type];
r.push(val);
} else if (temp[val].indexOf(type) < 0) {
temp[val].push(type);
r.push(val);
}
}
return r;
}

var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(aa));

方案三 排序后相邻去除法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
* 给传入数组排序,排序后相同值相邻,
* 然后遍历时,新数组只加入不与前一值重复的值。
* 会打乱原来数组的顺序
* */
function uniq(array){
array.sort();
var temp=[array[0]];
for(var i = 1; i < array.length; i++){
if( array[i] !== temp[temp.length-1]){
temp.push(array[i]);
}
}
return temp;
}

var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(aa));

方案四 数组下标法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
*
* 还是得调用“indexOf”性能跟方法1差不多,
* 实现思路:如果当前数组的第i项在当前数组中第一次出现的位置不是i,
* 那么表示第i项是重复的,忽略掉。否则存入结果数组。
* */
function uniq(array){
var temp = [];
for(var i = 0; i < array.length; i++) {
//如果当前数组的第i项在当前数组中第一次出现的位置是i,才存入数组;否则代表是重复的
if(array.indexOf(array[i]) == i){
temp.push(array[i])
}
}
return temp;
}

var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(aa));

方案五 优化遍历数组法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 思路:获取没重复的最右一值放入新数组
/*
* 推荐的方法
*
* 方法的实现代码相当酷炫,
* 实现思路:获取没重复的最右一值放入新数组。
* (检测到有重复值时终止当前循环同时进入顶层循环的下一轮判断)*/
function uniq(array){
var temp = [];
var index = [];
var l = array.length;
for(var i = 0; i < l; i++) {
for(var j = i + 1; j < l; j++){
if (array[i] === array[j]){
i++;
j = i;
}
}
temp.push(array[i]);
index.push(i);
}
console.log(index);
return temp;
}

var aa = [1,2,2,3,5,3,6,5];
console.log(uniq(aa));