This is my third article about getting started
The last article took a look at the array API and got a clear picture of it as a whole. This article will implement some of the array apis by hand and see how they work from the ground up…
Handwritten every
On the first source
Array.prototype._every = function(callBack, thisArg) {
if(this= =null) {
throw new TypeError()}if(typeofcallBack ! = ='function') {
throw new TypeError()}/ / the problem 1
//if(thisArg == null) {
// thisArg = window
/ /}
const obj = Object(this)
const len = obj.length >>> 0 2 / / problem
for(let i = 0; i < len; i++) {
if(i inobj && ! callBack.call(thisArg, obj[i], i, obj)) {return false}}return true // If it is an empty array, return true
}
Copy the code
The basic idea is as follows:
- Security considerations, for
this
andcallBack
Determine whether it fits the type. - Abstract this as an object (generality), and get the converted
length
. - Core operation, while iterating through a number setSkip the emptyIf there is a dissatisfaction
callBack
The return offalse
.
To answer questions that appear in the code:
Question 1: Why not consider thisArg null or undefined? Because the code uses call to bind this. ThisArg is null or undefined internally. Question 2: What is the use of obj.length >>> 0? >>> 0 does three things :(1) convert a non-numeric type to a number; (2) Convert the numeric type to a 32-bit unsigned integer. So, it also has the side effect that for negative x it converts it to 2^32 + x.
Handwritten filter
The source code is as follows:
Array.prototype._filter = function(callBack, thisArg) {
if(this= =null) {
throw new TypeError()}if(typeofcallBack ! = ='function') {
throw new TypeError()}// if(thisArg == null) {
// thisArg = window // undefined in strict mode
// }
const obj = Object(this)
let len = obj.length >>> 0
const result = new Array(len) // Preallocates the length
let index = 0
for(let i = 0; i < len; i++) {
if(i in this && callBack.call(thisArg, obj[i], i, obj)) {
result[index++] = obj[i]
}
}
result.length = index // Adjust the length to the right state
return result
}
Copy the code
The thinking is basically the same…
Handwritten reduce
Source:
Array.prototype._reduce = function(callBack, initialValue) {
if(this= =null) {
throw new TypeError()}if(typeofcallBack ! = ='function') {
throw new TypeError()}const obj = Object(this)
const len = obj.length >>> 0
/ / the problem 1
const hasInit = arguments.length > 1
if(len === 0 && !hasInit) {
throw new TypeError()}2 / / problem
let accumulator, i = 0
if(hasInit) {
accumulator = initialValue
} else {
while(i < len && ! (iin obj)) {
i++
}
if(i >= len) {
throw new TypeError()
}
accumulator = obj[i++]
}
while(i < len) {
if(i in obj) {
3 / / problem
accumulator = callBack(accumulator, obj[i], i, obj)
}
++i
}
return accumulator
}
Copy the code
To answer questions that appear in the code:
Question 1: How do you determine if an initialValue is provided? Use the initialValue! == undefined Cannot use initialValue! == undefined to determine whether initialValue is provided. It cannot determine if initialValue is assigned to undefined.
Problem 2: Internal reduce does not provideinitialValue
When,accmulator
What is the initial value of phi?
Note: When not providedinitialValue
The initial value for accmulator is the firstThe assigned item(Empty array error). It doesn’t take into account unassigned values. I didn’t think about this when I first wrote the code, which is ridiculous…
Q3: How is the accumulator value modified?
Note:accumulator
Is each iteration,callBack
Assigns the return value toaccumulator
. That is to say,accumulator
Is made up ofcallBack
The return value of the
Because of the use of lessaccumulator
Is it handled by some kind of reactive operation… A little silly 0.0
Handwritten includes
Source:
Array.prototype._includes = function(value, fromIndex) {
if(this= =null) {
throw new TypeError()}const obj = Object(this)
const len = obj.length >>> 0
if(len === 0) { // Return false if the array is empty
return false
}
/ / the problem 1
fromIndex = fromIndex | 0
2 / / problem
let n = Math.max(fromIndex < 0 ? len - Math.abs(fromIndex) : fromIndex, 0)
const sameValueZero = (x, y) = >x === y || (x ! == x && y ! == y)while(n < len) {
if(sameValueZero(value, obj[n])) {
return true
}
n++
}
return false
}
Copy the code
To answer questions that appear in the code:
Question 1: fromIndex = fromIndex | 0? FromIndex | 0 has two functions: (1), converts fromIndex number type. (2), converts fromIndex 32-bit signed integer. Notice that there are signs. Question 2: What if fromIndex is negative? From the code, if fromIndex is negative, length-math.abs (fromIndex) is used instead. If length-math. abs(fromIndex) is less than 0, replace it with 0.
Give it a thumbs up if you think it helps