介绍
在本文中,分享最流行的 JavaScript 方法,但都是从零开始实现的。
对提升编码能力,理解源码能力有一定提升。这只是其工作原理的简单版本,ECMAScript 中指定的实际方法要复杂得多。
本文提到的方法有:
map, reduce, filter, sort, every, includes, slice, splice, shift, indexOf.
在实现前先理解以上方法的api和使用
map
const fakeMap = function(callback) {
const newArray = []
// 'this' refers to the array
for (let i = 0; i < this.length; i++)
newArray[i] = callback(this[i], i)
return newArray
}
Array.prototype.fakeMap = fakeMap;
[1, 2, 3].fakeMap(n => n + 1) // output [2, 3, 4]
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
reduce
const fakeReduce = function(callback, accumulator) {
for (let i = 0; i < this.length; i++)
accumulator = callback(accumulator, this[i])
return accumulator
}
Array.prototype.fakeReduce = fakeReduce
const reducer = (previousValue, currentValue) => previousValue + currentValue;
[1, 2, 3].fakeReduce(reducer, 0) // output 6
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
filter
const fakeFilter = function(callback) {
const newArray = []
for (let i = 0; i < this.length; i++) {
if (callback(this[i]))
newArray.push(this[i])
}
return newArray
}
Array.prototype.fakeFilter = fakeFilter;
[1, 2, 3, 4, 5].fakeFilter(n => n > 2) // output [3, 4, 5]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sort
const fakeSort = function(callback) {
const newArray = [...this]
for (let i = 0; i < newArray.length; i++) {
for (let j = 0; j < newArray.length - 1; j++) {
if (callback(newArray[j], newArray[j + 1]) > 0) {
const temp = newArray[j + 1]
newArray[j + 1] = newArray[j]
newArray[j] = temp
}
}
}
// array is sorted
return newArray
}
Array.prototype.fakeSort = fakeSort;
[3, 5, 1, 4, 2].fakeSort((a, b) => a - b) // output [1, 2, 3, 4, 5]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
every
const fakeEvery = function(callback) {
for (let i = 0; i < this.length; i++) {
if (!callback(this[i]))
return false
}
return true
}
Array.prototype.fakeEvery = fakeEvery;
[1, 2, 3, 4, 5].fakeEvery(n => n > 3) // output false
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
includes
const fakeIncludes = function(item) {
for (let i = 0; i < this.length; i++) {
if (this[i] === item)
return true
}
return false
}
Array.prototype.fakeIncludes = fakeIncludes;
[1, 2, 3, 4, 5].fakeIncludes(5) // output true
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
slice
const fakeSlice = function(start, end) {
const newArray = []
if (!end) {
for (let i = 0; i < this.length; i++) {
if (i >= start)
newArray.push(this[i])
}
return newArray
}
for (let i = 0; i < this.length; i++) {
if (i >= start && i <= end)
newArray.push(this[i])
}
return newArray
}
Array.prototype.fakeSlice = fakeSlice;
[1, 2, 3, 4, 5].fakeSlice(2, 3) // output [3, 4]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
splice
const fakeSplice = function(start, deleteCount, ...items) {
let newArray = []
// if we only provide start fakeSplice(start)
if (!deleteCount) {
for (let i = 0; i < this.length; i++) {
if (i < start)
newArray.push(this[i])
}
this.length = 0
this.push.apply(this, newArray)
return
}
// if we only provide start and deleteCount fakeSplice(start, deleteCount)
if (!items) {
for (let i = 0; i < this.length; i++) {
if (i < start || i >= start + deleteCount)
newArray.push(this[i])
}
this.length = 0
this.push.apply(this, newArray)
return
}
// if we provide all arguments to the function
for (let i = 0; i < this.length; i++) {
if (i === start + deleteCount)
newArray = [...newArray, ...items]
if (i < start || i >= start + deleteCount)
newArray.push(this[i])
}
this.length = 0
this.push.apply(this, newArray)
}
Array.prototype.fakeSplice = fakeSplice
const planets = [
'Mercury',
'Venus',
'Earth',
'Mars',
'Jupiter',
'Saturn',
'Uranus',
'Neptune',
]
planets.fakeSplice(2, 2, 'Pluto')
console.log(planets) // output ["Mercury", "Venus", "Pluto", "Jupiter", "Saturn", "Uranus", "Neptune"]
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
45
46
47
48
49
50
51
52
53
54
55
56
57
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
45
46
47
48
49
50
51
52
53
54
55
56
57
shift
const fakeShift = function() {
const newArray = []
for (let i = 1; i < this.length; i++)
newArray.push(this[i])
this.length = 0
this.push.apply(this, newArray)
}
Array.prototype.fakeShift = fakeShift
const arr = [1, 2, 3, 4, 5]
arr.fakeShift()
console.log(arr) // output [2, 3, 4, 5]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
indexOf
const fakeIndexOf = function(item) {
for (let i = 0; i < this.length; i++) {
if (item === this[i])
return i
}
return -1
}
Array.prototype.fakeIndexOf = fakeIndexOf;
[1, 2, 3, 4, 5].fakeIndexOf(4) // output 3
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
结论
我们刚刚在 JavaScript 中实现了最常用的方法,并更好地了解了它们的工作原理,以便我们可以更有效地使用它们。
plurality should not be posited without necessity. 如无必要,勿增实体。