JavaScript 基础 - Array对象

一,静态方法

1,Array.isArray ()

语法:Array.isArray ( arg )

作用:判断 arg 是否为数组。

二,实例方法

转换:

Array.prototype.join ( )

语法:Array.prototype.join (分隔符)

将数组中的所有元素使用分隔符连接成字符串,省略分隔符则使用 ‘,’ 连接。

1
2
3
4
5
var a = ['Wind', 'Rain', 'Fire'];
var myVar1 = a.join(); // myVar1的值变为"Wind,Rain,Fire"
var myVar2 = a.join(', '); // myVar2的值变为"Wind, Rain, Fire"
var myVar3 = a.join(' + '); // myVar3的值变为"Wind + Rain + Fire"
var myVar4 = a.join(''); // myVar4的值变为"WindRainFire"

Array.prototype.toString ( )

首先对数组中的每个元素进行 toString() 操作,然后再调用 join() 方法连接成字符串(由逗号分隔)。

toString() 会优先调用自身对象的 join() 方法

1
2
3
4
5
6
var monthNames = ['Jan', 'Feb', 'Mar', 'Apr'];

monthNames.join = function () {
console.log("my join");
}
monthNames.toString(); // my join

Array.prototype.toLocaleString ( )

首先对数组中的每个元素使用各自的 toLocaleString() 方法转成字符串,
再将这些字符串用一个特定语言环境的分隔符(例如一个逗号 “,”)分隔。

1
2
3
4
5
6
7
8
var number = 1337;
var date = new Date();
var myArr = [number, date, "foo"];

var str = myArr.toLocaleString();

// 假定运行在中文(zh-CN)环境,北京时区
console.log(str); // 1337,2016/5/13 下午3:41:33,foo

组合:

Array.prototype.concat ( arguments )

语法:Array.prototype.concat ( [ item1 [ , item2 [ , … ] ] ] )

将传入的数组或非数组值与原数组合并成一个新的数组返回。

原数组中的元素有两种被拷贝的方式:原始值复制的是值,对象值复制的是引用。

增删:

Array.prototype.push ( arguments )

语法: Array.prototype.push ( …items )

从数组的末尾,添加一个或多个元素,并返回 length 属性值。

1
2
3
4
5
6
7
a = {'0':'a', '1':'b', '2':'c'};

Array.prototype.push.call(a,'d') // 1
console.log(a); // Object {0: "d", 1: "b", 2: "c", length: 1}

Array.prototype.push.call(a,'e') // 2
console.log(a); // Object {0: "d", 1: "e", 2: "c", length: 2}

Array.prototype.pop ( )

从数组的末尾,删除一个元素,并返回,如果 length0,则返回 undefined

1
2
3
4
a = {'0':'a', '1':'b', '2':'c'};

Array.prototype.pop.call(a); // undefined
console.log(a); // Object {0: "a", 1: "b", 2: "c", length: 0}

Array.prototype.unshift ( arguments )

语法: Array.prototype.unshift ( …items )

从数组的头部,添加一个或多个元素,并返回 length 属性值。

1
2
3
4
5
6
7
a = {'0':'a', '1':'b', '2':'c'};

Array.prototype.unshift.call(a,'d') // 1
console.log(a); // Object {0: "d", 1: "b", 2: "c", length: 1}

Array.prototype.unshift.call(a,'e') // 2
console.log(a); // Object {0: "e", 1: "d", 2: "c", length: 2}

Array.prototype.shift ( )

从数组的头部,删除一个元素,并返回,如果 length0,则返回 undefined

1
2
3
4
a = {'0':'a', '1':'b', '2':'c'};

Array.prototype.shift.call(a); // undefined
console.log(a); // Object {0: "a", 1: "b", 2: "c", length: 0}

Array.prototype.slice ( arguments )

语法: Array.prototype.slice (start, end)

把数组中的一部分浅复制存入一个新的数组对象中,并返回。

区间: [start, end)

提取原数组中,索引从 startend 的所有元素(包含 start,但不包含 end)。

start 省略则默认为 0end 省略则默认为数组的 length 属性值。

Array.prototype.slice (0, end) 可以解释为,复制数组的前 end 个元素。

Array.prototype.slice (start) 可以解释为,删除数组的前 start 个元素。

1
2
3
4
5
6
7
8
9
a = {'0':'a', '1':'b', '2':'c'};

Array.prototype.slice.call(a); // []

a.length = 1
Array.prototype.slice.call(a); // ["a"]

a.length = 2
Array.prototype.slice.call(a); // ["a", "b"]

slice() 方法常用来将一个类数组(Array-like)对象/集合转换成一个数组。

注意:

1
2
3
Array.prototype.slice.call(arguments)
// 简写
[].slice.call(arguments)

以上五种方法都可以通过 callapply 方法应用于一个类数组(array-like)对象上(String 类型除外)。

push(), pop(), unshift(), shift() 方法会根据数组的 length 属性值来决定要进行操作的位置。

如果 length 属性值不能被转化为一个数值或者不存在,则会先修改或添加 length 属性值为 0,再进行后续的操作。

slice() 方法在操作没有 length 属性的对象时,会返回一个空数组( [ ] )。

Array.prototype.splice ( arguments )

语法: Array.prototype.splice (start, deleteCount , …items )

从指定位置(start),删除指定长度的元素(deleteCount),并添加新元素(…items),

会改变原数组,并返回由被删除的元素组成的一个新数组。

参数长度等于 0,不操作,
返回空数组。

参数长度等于 1,做删除操作,
从指定位置开始删除到数组末尾,返回被删除的数组,
如果指定位置大于数组长度,则不操作,返回空数组。

参数长度等于 2,删除操作,
从指定位置开始删除固定长度的元素,返回被删除的数组,
如果删除长度等于 0,则不操作,返回空数组。

参数长度大于 2,删除并插入操作,
从指定位置开始删除固定长度的元素,并指定位置插入一个或多个新元素,返回被删除的数组,
如果删除长度等于 0,则不操作,返回空数组。

参数:

start:起始位置索引。

如果 start < 0,则 start 等于 length+start0 之间的最大值。

否则 start 等于 length+start0 之间的最小值。

deleteCount:删除元素的长度,deleteCount 的值等于第二个参数。

如果 arguments.length == 0,则 deleteCount = 0

如果 arguments.length == 1,则 deleteCount = length - 计算后的 start

如果 arguments.length >= 2,则 deleteCount = deleteCount

…items:添加的一个或多个新元素。

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
var myFish = ["angel", "clown", "mandarin", "surgeon"];

// 从第 2 位开始删除 0 个元素,插入 "drum"
var removed = myFish.splice(2, 0, "drum");
// myFish: ["angel", "clown", "drum", "mandarin", "surgeon"]
// removed:[]

// 从第 3 位开始删除 1 个元素
removed = myFish.splice(3, 1);
// myFish:["angel", "clown", "drum", "surgeon"]
// removed:["mandarin"]

// 从第 2 位开始删除 1 个元素,然后插入 "trumpet"
removed = myFish.splice(2, 1, "trumpet");
// myFish: ["angel", "clown", "trumpet", "surgeon"]
// removed:["drum"]

// 从第 0 位开始删除 2 个元素,然后插入 "parrot", "anemone" 和 "blue"
removed = myFish.splice(0, 2, "parrot", "anemone", "blue");
// myFish:["parrot", "anemone", "blue", "trumpet", "surgeon"]
// removed:["angel", "clown"]

// 从第 3 位开始删除 2 个元素
removed = myFish.splice(3, Number.MAX_VALUE);
// myFish: ["parrot", "anemone", "blue"]
// removed:["trumpet", "surgeon"]

排列:

Array.prototype.reverse ( )

反转数组,在操作类数组(array-like)对象时,会根据其 length 属性值,决定反转的长度。

1
2
a = {'0':'a', '1':'b', '2':'c',length:2};
[].reverse.call(a); // Object {0: "b", 1: "a", 2: "c", length: 2}

Array.prototype.sort ( comparefn )

对数组的元素做原地的排序,并返回这个数组,sort() 方法是不稳定的

默认按照字符串的 Unicode 码进行排序。

如果指明了 comparefn ,那么数组会按照调用该函数的返回值排序。

comparefn (x, y) 函数:

返回 <= 0 :x, y 位置不变,返回 > 0 :x, y 位置交换。

扩展阅读:洗牌算法

Fisher–Yates Shuffle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function shuffle(array) {
var m = array.length, t, i;

// While there remain elements to shuffle…
while (m) {

// Pick a remaining element…
i = Math.floor(Math.random() * m--);

// And swap it with the current element.
t = array[m];
array[m] = array[i];
array[i] = t;
}

return array;
}

如何测试洗牌程序

数组的完全随机排列

索引:

Array.prototype.indexOf ( )

语法: Array.prototype.indexOf ( searchElement [ , fromIndex ] )

使用严格相等在数组中正向查找指定元素并返回其第一个索引值,没有则返回 -1

fromIndex:开始查找的位置,默认 0

1
2
3
4
5
6
var array = [2, 9, 9];
array.indexOf(2); // 0
array.indexOf(7); // -1
array.indexOf(9, 2); // 2
array.indexOf(2, -1); // -1
array.indexOf(2, -3); // 0

正向查找数组中指定元素并返回其所有索引。

1
2
3
4
5
6
7
8
9
var indices = [];
var array = ['a', 'b', 'a', 'c', 'a', 'd'];
var element = 'a';
var idx = array.indexOf(element);
while (idx != -1) {
indices.push(idx);
idx = array.indexOf(element, idx + 1);
}
console.log(indices); // [0, 2, 4]

Array.prototype.lastIndexOf ( )

语法: Array.prototype.lastIndexOf ( searchElement [ , fromIndex ] )

使用严格相等在数组中逆向查找指定元素并返回其第一个索引值,没有则返回 -1

fromIndex:开始查找的位置,默认 数组长度 - 1。

1
2
3
4
5
6
7
var array = [2, 5, 9, 2];
array.lastIndexOf(2); // 3
array.lastIndexOf(7); // -1
array.lastIndexOf(2, 3); // 3
array.lastIndexOf(2, 2); // 0
array.lastIndexOf(2, -2); // 0
array.lastIndexOf(2, -1); // 3

逆向查找数组中指定元素并返回其所有索引。

1
2
3
4
5
6
7
8
9
10
11
12
var indices = [];
var array = ['a', 'b', 'a', 'c', 'a', 'd'];
var element = 'a';
var idx = array.lastIndexOf(element);

while (idx != -1) {
indices.push(idx);
// 当 idx == 0 时 fromIndex == -1,会造成查找无限循环。所以,这里要单独处理这种情况。
idx = (idx > 0 ? array.lastIndexOf(element, idx - 1) : -1);
}

console.log(indices); // [4, 2, 0];

遍历:

callbackfn( currentValue [ , index [ , Array ] ] )

Array.prototype.every ( )

语法: Array.prototype.every ( callbackfn [ , thisArg ] )

用来测试数组中的所有元素是否都通过了指定函数的测试。

every() 方法为数组中的每个元素调用一次 callbackfn 函数,
直到找到一个在 callbackfn 中返回 false 的元素,并返回 false,否则返回 true

Array.prototype.some ( )

语法: Array.prototype.some ( callbackfn [ , thisArg ] )

用来测试数组中的某些元素是否通过了指定函数的测试。

some() 方法为数组中的每个元素调用一次 callbackfn 函数,
直到找到一个在 callbackfn 中返回 “真值”(布尔值为 true 的值)的元素,并返回 true。否则返回 false

Array.prototype.filter ( )

Array.prototype.filter ( callbackfn [ , thisArg ] )

用来测试数组中的所有元素,返回一个包含所有通过测试元素的新数组。

filter() 方法为数组中的每个元素调用一次 callbackfn 函数,
并返回一个由所有在 callbackfn 中返回 “真值”(布尔值为 true 的值)的元素所组成的新数组。

Array.prototype.forEach ( )

语法: Array.prototype.forEach ( callbackfn [ , thisArg ] )

forEach() 方法为数组中的每个元素都调用一次 callbackfn 函数,总是返回 undefined

对象复制函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function copy(obj) {
var copy = Object.create(Object.getPrototypeOf(obj));
var propNames = Object.getOwnPropertyNames(obj);

propNames.forEach(function(name) {
var desc = Object.getOwnPropertyDescriptor(obj, name);
Object.defineProperty(copy, name, desc);
});

return copy;
}

var obj1 = { a: 1, b: 2 };
var obj2 = copy(obj1); // obj2 looks like obj1 now

注意:

除了抛出异常,没有办法中止或者跳出 forEach 循环,
forEach() 方法内使用 break, continue 会抛出 SyntaxError 异常。
如果需要这样做,那么不要使用 forEach() 方法,用一个简单的循环即可。

1
2
3
4
5
6
7
8
9
10
11
function logArrayElements(element, index, array) {
if(index==1) {
break;
}
console.log("a[" + index + "] = " + element);
}
[2, 5, 9].forEach(logArrayElements);
// logs:
// a[0] = 2
// a[1] = 5
// a[2] = 9

如果您正在测试一个数组里的元素是否符合某条件,且需要返回一个布尔值,
那么可以使用 Array.every() 方法 或 Array.some() 方法。

Array.prototype.map ( )

语法: Array.prototype.map ( callbackfn [ , thisArg ] )

map() 方法为数组中的每个元素都调用一次 callbackfn 函数,返回一个由所有返回值组成的新数组

注意:

如果数组中的元素被更改,那么传入 callbackfn 的值将是更改后的值。

every(), some(), filter(), forEach(), map() 方法在调用时已存放了数组长度,
callbackfn 中追加到数组中的新元素,被删除的元素 和 未被赋值的元素 都不会被处理。

1
2
3
4
5
6
7
function isBigEnough(element, index, array) {
array.push(index);
return (element >= 10);
}
var arr = [12, 54, 18, 130, 44];
arr.every(isBigEnough); // true
console.log(arr); // [12, 54, 18, 130, 44, 0, 1, 2, 3, 4]

累加:

callbackfn( previousValue, currentValue, currentIndex, array )

previousValue:上一次 callbackfn() 函数的返回值。

currentValue:数组中当前被处理的元素。

currentIndex: currentValue 在数组中的索引。

callbackfn() 函数在第一次被调用时有两种情况

如果存在 initialValue,则 previousValue 等于 initialValuecurrentValue 等于数组的第一个元素

如果不存在 initialValue,则 previousValue 等于数组的第一个元素,currentValue 等于第二个元素。

Array.prototype.reduce ( )

语法: Array.prototype.reduce ( callbackfn [ , initialValue ] )

reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始合并,最终返回一个值。

没有初始值:

1
2
3
4
[0,1,2,3,4].reduce(function(previousValue, currentValue, index, array){
return previousValue + currentValue;
});
// 调用四次,返回 10

有初始值:

1
2
3
4
[0,1,2,3,4].reduce(function(previousValue, currentValue, index, array){
return previousValue + currentValue;
}, 10);
// 调用五次,返回 10

数组扁平化:

1
2
3
4
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {
return a.concat(b);
});
// flattened is [0, 1, 2, 3, 4, 5]

Array.prototype.reduceRight ( )

语法: Array.prototype.reduceRight ( callbackfn [ , initialValue ] )

reduceRight() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从右到左)开始合并,最终返回一个值。