数组

数组和字符串之间相互转换

split()

split()函数是将字符串转换为数组

1
2
3
4
5
var sentence = 'the quick brown for jumped over the lazy dog'
var words = sentence.split(' ')
for (let i = 0; i < words.length; i++) {
console.log("word " + i + ': ' + words[i])
}

输出

1
2
3
4
5
6
7
8
9
word 0: the
word 1: quick
word 2: brown
word 3: for
word 4: jumped
word 5: over
word 6: the
word 7: lazy
word 8: dog

join()、toString()

join() toString()两个方法可以将数组转化为字符串。这两个方法都返回一个包含数组所有元素的字符串,各元素之间默认用逗号分隔开

1
2
3
4
5
var names = ['David', 'Cynthia', 'Raymond', 'mike']
var namestr = names.join()
console.log(namestr)
var namestr_1 = names.toString()
console.log(namestr_1)

输出

1
2
David,Cynthia,Raymond,mike
David,Cynthia,Raymond,mike

如果为join()传入参数,则各元素之间使用传入的参数隔开

1
2
3
var names = ['David', 'Cynthia', 'Raymond', 'mike']
var namestr = names.join(';')
console.log(namestr)

输出

1
David;Cynthia;Raymond;mike

存取函数

indexOf()、lastIndexOf()

indexOf()函数是最常用的存取函数之一,用来查找传进来的参数在目标数组中是否存在。如果目标数组包含该参数,就返回该元素在数组中的索引;如果不包含,就返回-1

1
2
3
var name = ['jake', 'yu', 'lao']
console.log('yu is at: ' + name.indexOf('yu'))
console.log('aaa is at: ' + name.indexOf('aaa'))

输出

1
2
yu is at: 1
aaa is at: -1

如果数组中包含多个相同的元素,indexOf()函数总是返回第一个与参数相同的元素的索引。lastIndexOf()函数返回相同元素的最后一个元素的索引,如果没有找到相同元素,则返回-1

findIndex()

除IE以外的所有浏览器(非边缘)都支持Array.prototype.findIndex。但是Polyfill很好的解决了这个问题

1
var indexOfStevie = myArray.findIndex(i => i.hello === "stevie");

兼容

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex
if (!Array.prototype.findIndex) {
Object.defineProperty(Array.prototype, 'findIndex', {
value: function(predicate) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
}

var o = Object(this);

// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;

// 3. If IsCallable(predicate) is false, throw a TypeError exception.
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}

// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
var thisArg = arguments[1];

// 5. Let k be 0.
var k = 0;

// 6. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kValue be ? Get(O, Pk).
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
// d. If testResult is true, return k.
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return k;
}
// e. Increase k by 1.
k++;
}

// 7. Return -1.
return -1;
}
});
}

由已知数组创建新数组

concat()、splice()

concat()splice()方法允许通过已有的数组创建新数组。concat()方法可以合并多个数组创建一个新数组,splice()方法截取一个数组的子集创建一个新数组。

concat()

该方法的发起者是一个数组,参数是另外一个数组或者多个数组。作为参数的数组,其中的所有元素都被连接到调用concat()方法的数组后面。下面的程序展示了concat()方法的工作原理:

1
2
3
4
5
6
7
var cisDept = ['jake', 'mike', 'jenn']
var dmpDept = ['bryan', 'cynthia']
var dmpDept_2 = ['bryan', 'cynthia']
var itDiv = cisDept.concat(dmpDept)
console.log(itDiv)
var itDiv = cisDept.concat(dmpDept, dmpDept_2)
console.log(itDiv)

输出

1
2
[ 'jake', 'mike', 'jenn', 'bryan', 'cynthia' ]
[ 'jake', 'mike', 'jenn', 'bryan', 'cynthia', 'bryan', 'cynthia' ]

splice()

splice()方法从现有数组里截取一个新数组。该方法的第一个参数是截取的起始索引,第二个参数是截取的长度。该方法会改变原来的数组。如果第二个参数传入的是0,则不删除

1
2
3
4
var num = [1, 2, 3, 4, 5, 6]
var numSpl = num.splice(1, 3)
console.log(numSpl)
console.log(num)

输出

1
2
[ 2, 3, 4 ]
[ 1, 5, 6 ]

添加和删除

push()、unshift()

push()方法会将一个元素添加到数组末尾:

1
2
3
var nums = [1, 2, 3, 4, 5]
nums.push(6, 7, 8)
console.log(nums)

输出

1
[ 1, 2, 3, 4, 5, 6, 7, 8 ]

unshift()方法会将一个元素添加到数组开头

1
2
3
var nums = [1, 2, 3, 4, 5]
nums.unshift(6, 7, 8)
console.log(nums)

输出

1
[ 6, 7, 8, 1, 2, 3, 4, 5 ]

pop()、shift()

pop()方法可以删除数组末尾的元素,并返回该元素

1
2
3
4
var nums = [1, 2, 3, 4, 5]
var popNum = nums.pop()
console.log(nums) //[ 1, 2, 3, 4 ]
console.log(popNum) //5

shift()方法可以删除数组开头的元素,并返回该元素

1
2
3
4
var nums = [1, 2, 3, 4, 5]
var popNum = nums.shift()
console.log(nums) //[ 2, 3, 4, 5 ]
console.log(popNum) //1

splice()

使用splice()方法为数组添加元素,需提供如下参数

  • 起始索引
  • 需要删除的元素个数(不删除为0)
  • 想要添加的元素
1
2
3
var nums = [1, 2, 3, 4, 5]
nums.splice(3, 0, 11, 11, 11, 11, 11)
console.log(nums) //[ 1, 2, 3, 11, 11, 11, 11, 11, 4, 5 ]

排序

reverse()

reverse()可以对数组进行翻转

1
2
3
var nums = [1, 2, 3, 4, 5]
nums.reverse()
console.log(nums) //[ 5, 4, 3, 2, 1 ]

sort()

如果数组是字符串类型,那么数组的可变方法sort()就非常好使:

1
2
3
var name = ['David', 'Mike', 'Cynthia', 'Clayton']
name.sort()
console.log(name) //[ 'Clayton', 'Cynthia', 'David', 'Mike' ]

但是如果数组元素是数字类型,sort()方法的排序结果就不能让人满意了

1
2
3
var nums = [3, 1, 2, 100, 4, 200]
nums.sort()
console.log(nums) //[ 1, 100, 2, 200, 3, 4 ]

sort()方法是按照字典顺序对元素进行排序,因此它假定元素都是字符串类型。为了让sort()方法也能排序数字类型的元素,可以在调用方法是传入一个比较大小的函数。

1
2
3
4
5
var nums = [3, 1, 2, 100, 4, 200]
nums.sort((num1, num2) => {
return num1 - num2
})
console.log(nums) //[ 1, 2, 3, 4, 100, 200 ]

迭代器方法

这些方法对数组中的每个元素应用一个函数,可以返回一个值、一组值或者一个新数组

forEach()

该方法接受一个函数作为参数,对数组中的每个元素使用该函数。

1
2
3
4
var nums = [1, 2, 3, 4, 5, 6, 7, 8]
nums.forEach((item, index) => {
console.log(item, item * item)
})

输出

1
2
3
4
5
6
7
8
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64

every()

该方法接受一个返回值为布尔类型的函数,对数组中的每个元素使用该函数。如果对于所有的元素该函数返回值均为true,则该方法返回true

1
2
3
4
5
6
7
8
9
10
11
12
13
var nums = [2, 4, 6, 8]
isEven = (num) => {
return num % 2 == 0
}

var even = nums.every(isEven)

if (even) {
console.log('even is true')
} else {
console.log('even is false')
}
//even is true
1
2
3
4
5
6
7
8
9
10
11
12
13
var nums = [1, 2, 4, 6, 8]
isEven = (num) => {
return num % 2 == 0
}

var even = nums.every(isEven)

if (even) {
console.log('even is true')
} else {
console.log('even is false')
}
//even is false

some()

some()方法也接受一个返回值为布尔类型的函数,只有有一个元素使得该函数返回true,该方法就返回true

1
2
3
4
5
6
7
8
9
10
11
12
13
function isEven(num) {
return num % 2 == 0
}

var nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var someEven = nums.some(isEven)

if (someEven) {
console.log('true')
} else {
console.log('false')
}
//true

reduce()

reduce()方法接受一个函数,返回一个值。该方法会从一个累加值开始,不断对累加值和数组中的后续元素调用该函数,直到数组中的最后一个元素,最后返回得到的累加值。

1
2
3
4
5
6
7
function add(runningTotal, currentValue) {
return runningTotal + currentValue
}

var nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var sum = nums.reduce(add)
console.log(sum) //55
1
2
3
4
5
6
7
8
9
add(1,2) --> 3
add(3,3) --> 6
add(6,4) --> 10
add(10,5) --> 15
add(15,6) --> 21
add(21,7) --> 28
add(28,8) --> 36
add(36,9) --> 45
add(45,10) --> 55

reduceRight()方法和reduce()方法不同,reduceRight()是从右到左执行

map()

map()forEach()有点儿像,对数组中的每个元素使用某个函数。两者区别是map()返回一个新的数组,该数组的元素是对原有元素应用某个函数得到的结果。

1
2
3
4
5
6
7
8
function curve(grade) {
return grade += 5
}

var grades = [77, 65, 81, 92, 83]

var newGrades = grades.map(curve)
console.log(newGrades) //[ 82, 70, 86, 97, 88 ]

filter()

filter()every()类似,传入一个返回值为布尔类型的函数。和every()方法不同的是,当对数组中的所有元素应用该函数,结果均为true时,该方法并不返回true,而是返回一个新数组,该数组包含应用该函数后的结果为true的元素。

1
2
3
4
5
6
7
8
9
10
11
12
function isEven(num) {
return num % 2 == 0
}

var nums = []

for (let i = 0; i < 20; i++) {
nums[i] = i + 1
}

var events = nums.filter(isEven)
console.log(events) //[ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 ]

一行代码生成数组

作者:SarjuHansaliya
原文:仅用一行生成[0, 1, …, N-1]数列

使用下面一行代码,我们就可以生成0…(N-1)数列。

ES5

1
Array.apply(null, {length: N}).map(Function.call, Number);

简要说明:

  1. Array.apply(null, {length: N}) 返回一个由undefined填充的长度为N的数组(例如 A = [undefined, undefined, …])。
  2. A.map(Function.call, Number) 返回一个长度为N的数组,它的索引为I的元素为Function.call.call(Number, undefined, I, A)的结果。
  3. Function.call.call(Number, undefined, I, A)可转化为Number(I),正好就是I。
  4. 结果为:[0, 1, …, N-1]。

ES6

这里用到了Array.from

1
Array.from(new Array(N),(val,index)=>index);

简要说明:

  1. A = new Array(N) 返回一个有N个_小孔_的数组 (例如 A = [,,,…], 但是对于x in 0…N-1时A[x] = undefined)。
  2. F = (val,index)=>index 即 function F (val, index) { return index; }。
  3. Array.from(A, F) 返回一个长度为N的数组,它的索引为I的元素为F(A[I], I)的结果,也就是I。
  4. 结果为:[0, 1, …, N-1]。

One More Thing

如果你需要[1, 2, …, N]序列, 方法1可改为:

1
2
3
Array.apply(null, {length: N}).map(function(value, index){
return index + 1;
});

方法2可改为:

1
Array.from(new Array(N),(val,index)=>index+1);