Array的属性和静态方法在这篇文章中,我们使用array表示数组对象;Array表示构造函数。每一小节会给出一个总结的纲要,后面会对其重点和易错点进行详细叙述。注意,这不是篇Array的参考文档,它只关注容易被web工程师忽略的细节。
概览
属性:
Array.length
Array.prototype
静态方法:
Array.isArray()
详细介绍
Array.length
length属性不能真正表示数组中定义的值的数目,它的默认值为“数字键”最大值+1。length不能填充数组,但是可以以此截断数组。
arr[5] = 'hello';
arr[1]; // => undefined
arr.length; // =>6
Array.prototype
鲜为人知的是,Array.prototype本身也是数组
Array.isArray(Array.prototype) // =>true
它本身拥有constructor和length两个属性。
Array改变自身的原型方法概览
删除
Array.prototype.pop()
删除数组的最后一个元素,并返回这个元素。
Array.prototype.shift()
删除数组的第一个元素,并返回这个元素。
增加
Array.prototype.push()
在数组的末尾增加一个或多个元素,并返回数组的新长度。
Array.prototype.unshift()
在数组的开头增加一个或多个元素,并返回数组的新长度。
Array.prototype.splice()
在任意的位置给数组添加或删除任意个元素。
调整顺序
Array.prototype.reverse()
颠倒数组中元素的排列顺序,即原先的第一个变为最后一个,原先的最后一个变为第一个。
Array.prototype.sort()
对数组元素进行排序,并返回当前数组。
详细介绍
push
push可以接受一个或多个参数,将其增加到数组末尾。
var arr1 = [1,2,3];
arr1.push('4');
arr1.push('5','6');
arr1.push(['7','8']); // arr[5] = [7,8]
console.log(arr1);
console.log(arr1.toString()); // =>1,2,3,4,5,6,7,8
也可以使用push合并两个数组
var vegetables = ['parsnip', 'potato'];
var moreVegs = ['celery', 'beetroot'];
// 等价于 vegetables.push('celery', 'beetroot')
Array.prototype.push.apply(vegetables, moreVegs);
console.log(vegetables); //=> ['parsnip', 'potato', 'celery', 'beetroot']
push被特意被设计成具有通用性;这个方法能够通过 call 或 apply 方法作用于类似数组的对象上。这意味着,当我们使用这样的函数应用时,上下文不一定是数组。push方法根据length属性判断新元素添加的位置,没有length属性这个方法将无法使用。
var obj = {
length: 0,
addElem: function addElem(elem) {
[].push.call(this, elem);
}
};
// Let's add some empty objects just to illustrate.
obj.addElem({time:'1'});
obj.addElem({time:'2'});
console.log(obj[0].time); // =>1
console.log(obj.length); // => 2
unshift与push基本相同,只是插入元素的位置在数组的开头。
unshift
unshift移除数组的第一个元素并使其他所有元素的索引-1。其返回值是删除的元素,如果数组为空,则返回undefined。
sort
sort方法不一定是稳定的,默认排序顺序是根据字符串Unicode码点。这意味着使用sort排序数字数组时一定要当心,因为比较时数字会被转化为字符串:
var scores = [1, 12, 21, 2];
scores.sort(); // [1, 12, 2, 21]
在Unicode码中,字符挨个比较。数字的出现顺序(0-9排列)>大写字母的出现顺序>小写字母的出现顺序。
sort接受一个函数参数,用于设置如何比较,这个函数接受两个参数:a, b即参与比较的数组元素。如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前。所以可以使用如下方式实现升序排序:
scores.sort(function (a, b) {
return a - b;
});
可以以此根据对象列表中对象的某个属性进行排序。
splice
splice() 方法通过删除现有元素和/或添加新元素来更改数组的内容,它会把删除掉的内容作为数组返回。
splice()方法接收3个参数:
start 指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位。
deleteCount 可选 整数,表示要移除的数组元素的个数。如果 deleteCount 被省略或大于start 之后的元素的总数,则start及其后面的元素都将被删除。
item1, item2 ... ... 可选 要添加进数组的元素,从start 位置开始。如果不指定,则 splice() 将只删除数组元素。
例如:
var arr = [1, 2, 3, 4, 5, 6];
console.log(arr.splice(0, 4)); //=> [1,2,3,4]
console.log(arr); //=>[5,6]
Array 不改变自身的原型方法
概览
Array.prototype.concat()
返回一个由当前数组和其它若干个数组或者若干个非数组值组合而成的新数组。
Array.prototype.join()
连接所有数组元素组成一个字符串。
Array.prototype.slice()
抽取当前数组中的一段元素组合成一个新数组。
Array.prototype.toString()
返回一个由所有数组元素组合而成的字符串。遮蔽了原型链上的 Object.prototype.toString() 方法。
Array.prototype.toLocaleString()
返回一个由所有数组元素组合而成的本地化后的字符串。遮蔽了原型链上的 Object.prototype.toLocaleString() 方法。
Array.prototype.indexOf()
返回数组中第一个与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。
Array.prototype.lastIndexOf()
返回数组中最后一个(从右边数第一个)与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。
concat
与join不同,concat既可以接受数组作为参数,也可以接受普通值作为参数。方法最后返回一个新的数组,对原来的数组不造成影响(但是引用是浅拷贝)
var arr1 = [1,2,3],
arr2 = [4,5],
newArr;
newArr = arr1.concat(arr2, 6);
console.log(newArr); // =>[1,2,3,4,5,6]
newArr[0] = 'hello';
console.log(arr1); // =>[1,2,3]
join、toString、toLocaleString()
join接受一个作为分隔符的参数,其默认值为',',如果数组的length属性为0,会导致join返回空字串。
Array.prototype.toString()遮蔽了Object的toString()方法,其内部调用数组的join()方法。
toLocaleString() 则会使数组中的元素使用各自的 toLocaleString 方法。比如下面的1337调用自己的toLocaleString方法,变成了字符串:1,337
(function(){
var number = 1337;
var date = new Date();
var myArr = [number, date, "foo"];
var str = myArr.toLocaleString();
console.log(str);
}())
1,337,2017/2/16 下午4:02:40,foo
slice()
slice()方法将数组的一部分浅拷贝, 返回到从开始到结束(不包括结束)选择的新数组对象。
它接收两个参数,start和end,它们都是可选的。
start的默认值是0,正数从0开始,负数从-1开始,表示倒数第n个数。获得的新数组包含start索引所对应的元素。
end的默认值是arr.length。获得的新数组不包含end索引所对应的元素。如果end的值大于数组长度,也会以数组长度作为结束索引。
slice 方法可以用来将一个类数组(Array-like)对象/集合转换成一个数组。你只需将该方法绑定到这个对象上。下述代码中 list 函数中的 arguments 就是一个类数组对象。
function list() {
return Array.prototype.slice.call(arguments);
}
var list1 = list(1, 2, 3); // [1, 2, 3]
indexOf vs lastIndexOf
一个是从前向后查找,一个是从后向前查找。二者都可接受第二个参数,是开始查找地方的索引。显然,前者from的默认值是0,后者from的默认值是arr.length-1。注意,indexOf采用的是严格判等模式。如果没有匹配的元素,那么返回-1;
遍历方法概览
Array.prototype.forEach()
为数组中的每个元素执行一次回调函数。
Array.prototype.every()
如果数组中的每个元素都满足测试函数,则返回 true,否则返回 false。
Array.prototype.some()
如果数组中至少有一个元素满足测试函数,则返回 true,否则返回 false。
Array.prototype.filter()
将所有在过滤函数中返回 true 的数组元素放进一个新数组中并返回。
Array.prototype.map()
返回一个由回调函数的返回值组成的新数组。
Array.prototype.reduce()
从左到右为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。
Array.prototype.reduceRight()
从右到左为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。
详细介绍
下面提到的函数都可以接受第二个参数,用来指定callback函数中this的值
every、some
every 方法为数组中的每个元素执行一次 callback 函数,直到它找到一个使 callback 返回 false(表示可转换为布尔值 false 的值)的元素。如果发现了一个这样的元素,every 方法将会立即返回 false。否则,callback 为每一个元素返回 true,every 就会返回 true。callback 只会为那些已经被赋值的索引调用。不会为那些被删除或从来没被赋值的索引调用。
与forEach类似,回调函数接受三个参数,分别是el, index和array
注意:every 遍历的元素范围在第一次调用 callback 之前就已确定了。在调用 every 之后添加到数组中的元素不会被 callback 访问到。
比如:
var arr = [1,2,3,4];
var condition = arr.every(function (el) {
return el < 5
});
console.log(condition); // true
some和every使用方法类似,区别在于使用some函数遍历数组时,只要有一个满足条件,即返回true.
filter
filter() 方法使用指定的函数测试所有元素,并创建一个包含所有通过测试的元素的新数组。
function isBigEnough(value) {
return value >= 10;
}
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// filtered is [12, 130, 44]
map
map() 方法返回一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组。
var arr = [1,2,3,4,5];
function inc(el) {
return el + 1
}
console.log(arr.map(inc)); // =>[2,3,4,5,6]
reduce vs reduceRight
reduce() 方法对累加器和数组的每个值应用一个函数 (从左到右,顾名思义,reduceRight是从右到左),以将其减少为单个值。
// a是上一个元素经过函数后的返回值,b是这个元素,c是这个元素的索引,d是数组本身
var sum = [0, 1, 2, 3].reduce(function(a, b, c, d) {
return a + b;
}, 0);
// sum is 6
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {
return a.concat(b);
}, []);
// flattened is [0, 1, 2, 3, 4, 5]