在js中,数组是一个拥有众多方法的对象,下面逐一进行分析。
数组的复制
var nums = [];
for(var i = 0; i < 10; i++){
nums[i] = i + 1;
}
var samenums = nums;
samenums[100] = 100;
nums[100] // 100
因为数组是一个对象,当采用如上的赋值方式时,samenums获得了nums数组的引用,因此改变samenums,就改变了nums,这种行为叫做浅复制。如果想要获得一样的数组又不想指向nums应该使用一个深复制函数
function copy(arr1, arr2){
for(var i = 0, len = arr1.length; i < len; i++){
arr2[i] = arr1[i];
}
}
var samenums = [];
copy(nums, samenums);
查找元素
数组对象中存在一个和字符串对象中相同的查找函数indexOf
var names = ['David', 'John', 'Jack'];
var position = names.indexOf('John') // return 1
var notfind = names.indexOf('Mary') // return -1
如果数组/字符串对象中包含多个相同的元素,indexOf返回第一个与参数相同的索引,lastIndexOf返回相同元素中最后一个索引。这两个方法都是ECMAScript5提供的,因此IE8以下浏览器不支持
将数组转化为字符串
将数组转化成字符串有两种相同的方法,join和toString
var names = ['David', 'John', 'Jack'];
var namestr = names.join(); // 'David,John,Jack'注意这边有逗号
namestr = names.toString(); //'David,John,Jack'
注意join比toString强的一点是可以带参数,默认是加逗号,比如经典的把字符串倒序的问题:
var str = 'abcde';
var str1 = Array.prototype.slice.call(str).reverse().join(); //'e,d,c,b,a'
var str2 = Array.prototype.slice.call(str).reverse().join(','); //与上面相同
var str3 = Array.prototype.slice.call(str).reverse().join(''); // 'edcba'
var str4 = Array.prototype.slice.call(str).reverse().toString(''); // 'e,d,c,b,a'
var str5 = str.split('').reverse().join('') // 'edcba'
由已有数组创建新数组
concat通过合并数组创建新数组,splice通过切割数组创建新数组
var names = ['David', 'John', 'Jack'];
var othernames = ['Lucy', 'Tony'];
var arr = names.concat(othernames); //arr为['David', 'John', 'Jack', 'Lucy', 'Tony'];
arr = names.splice(1, 1); // ['John', Jack]
arr = names.splice(1, 1, 'Lucy'); // ['Lucy', 'John', 'Jack'];
concat的参数可以数组也可以是元素,还可以接受多个参数
var arr1 = [1, 2],
arr2 = [3, 4],
arr3 = [5, 6];
var arr = [].concat(arr1, arr2, arr3, 7) //[1, 2, 3, 4, 5, 6, 7]
数组添加元素
push/pop方法从数组末尾增加/减少元素,shift/unshift可以从数组头部减少/增加元素,shift只能从头部删除第一个元素,而unshift可以从头部插入一组或一个元素。注意,push可以接收多个参数
var arr1 = [1, 2, 3]; // 我们想把数组变成[1, 2, 3, 4, 5, 6]
var arr2 = [4, 5, 6];
arr1.push(arr2) //这样得到了js的二维数组,不是我们想要的结果
arr1.push(4, 5, 6) //push可以接收多个参数,得到[1, 2, 3, 4, 5, 6]
Array.prototype.push.apply(arr1, arr2); //通过apply直接传入数组,也可以获得我们想要的结果
var obj = {'0': 4, '1': 5, '2': 6, length: 3};
Array.prototype.push.apply(arr1, obj); //通过apply还可以直接传入类数组对象
数组排序
第一个方法是reverse
var nums = [1, 2, 3, 4];
nums.reverse();
nums // 4, 3, 2, 1
第二个方法是sort,这个方法是为字符串数组量身定做的,如果是数字数组,则需要在sort中传入一个函数
var nums = [3, 1, 2, 100, 4, 200];
nums.sort(); // [1, 100, 2, 200, 3, 4];
nums.sort(function(num1, num2){
return num1 - num2
}) // [1, 2, 3, 4, 100, 200]
如果想比较的字段是在数组内部,如
var nums = [{id: 2}, {id: 9}, {id: 5}, {id: 4}];
nums.sort(function(a, b){
//按照id对对象进行排序
return a.id - b.id
})
注意: sort方法会改变原始数组。如果不想改变的话,可以用一个使用一个拷贝数组进行排序
var newNums = nums.concat().sort();
数组迭代器
第一个方法是forEach,接受一个函数做为参数,为每一个数组元素执行该函数
function square(num){
console.log(num * num);
}
[1, 2, 3, 4].forEach(square);
迭代器方法不对原数组造成影响。every方法接受一个返回值为布尔类型的函数,如果对于所有元素,该函数均返回true,则该方法返回true, 否则为false, some方法接受一个返回值为布尔类型的函数,只要有一个元素使得该函数返回true,该方法就返回true。 reduce方法接受一个函数,返回一个值,该方法会从一个累加值开始,不断对累加值和数组中的后续元素调用该函数
function add(lastValue, currentValue){
return lastValue + currentValue;
}
var nums = [1, 2, 3, 4, 5, 6];
var sum = nums.reduce(add); // 21
生成新数组的迭代器方法
第一个方法是map, 可以用一个新变量存储新数组,迭代器方法原有数组还是不受影响
var nums = [1, 2, 3];
var newnums = nums.map(function(v){
return v + 5;
})
// [6, 7, 8]
var newnums = nums.map(function(v, k){
return v + k
})
//函数第二个参数为索引 [1, 3, 5]
filter方法与every类似,传入一个返回值为布尔类型的函数,返回值为一个新数组,包含应用该函数最后结果为true的函数
var nums = [1, 2, 3, 4, 5];
function isBig(num){
return num >= 3;
}
var newnums = nums.filter(isBig); // [3, 4, 5]
数组的去重
使用indexOf的偷懒方法
Array.prototype.distinct = function(){
//注意,这里的length要动态去取,因为每次操作之后数组的长度可能发生了变化
for(var i = 0 ; i < this.length; i++){
var element = this[i];
//先将当前元素替换成null
this.splice(i, 1, null);
//检查数组中是否还存在相同元素
//存在的话将当前元素切掉
//splice方法直接改变了数组,slice则没有
this.indexOf(element) > 0 ?
this.splice(i, 1) :
this.splice(i, 1, element)
}
//将修改完的数组返回
return this;
}