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:

  1. Security considerations, forthisandcallBackDetermine whether it fits the type.
  2. Abstract this as an object (generality), and get the convertedlength.
  3. Core operation, while iterating through a number setSkip the emptyIf there is a dissatisfactioncallBackThe 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 provideinitialValueWhen,accmulatorWhat is the initial value of phi?

Note: When not providedinitialValueThe 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:accumulatorIs each iteration,callBackAssigns the return value toaccumulator. That is to say,accumulatorIs made up ofcallBackThe return value of the

Because of the use of lessaccumulatorIs 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