Problem

Write your version of method forEach that enhances all arrays such that you can call the array.forEach(callback, context) method on any array and it will execute callback on each element of the array. Method forEach should not return anything.

callback accepts the following arguments:

  • currentValue - represents the current element being processed in the array. It is the value of the element in the current iteration.
  • index - represents the index of the current element being processed in the array.
  • array - represents the array itself, allowing access to the entire array within the callback function.

The context is the object that should be passed as the function context parameter to the callback function, ensuring that the this keyword within the callback function refers to this context object.

Try to implement it without using the built-in array methods.

Examples

Example 1:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Input: 
arr = [1,2,3], 
callback = (val, i, arr) => arr[i] = val * 2, 
context = {"context":true}
Output: [2,4,6]
Explanation: 
arr.forEach(callback, context)  
console.log(arr) // [2,4,6]

The callback is executed on each element of the array.

Example 2:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Input: 
arr = [true, true, false, false], 
callback = (val, i, arr) => arr[i] = this, 
context = {"context": false}
Output: [{"context":false},{"context":false},{"context":false},{"context":false}]
Explanation: 
arr.forEach(callback, context) 
console.log(arr) // [{"context":false},{"context":false},{"context":false},{"context":false}]

The callback is executed on each element of the array with the right context.

Example 3:

1
2
3
4
5
Input: 
arr = [true, true, false, false], 
callback = (val, i, arr) => arr[i] = !val, 
context = {"context": 5}
Output: [false,false,true,true]

Constraints:

  • arr is a valid JSON array
  • context is a valid JSON object
  • fn is a function
  • 0 <= arr.length <= 10^5

Solution

Method 1 – Polyfill Using Prototype

Intuition

We want to add a custom forEach method to all arrays, mimicking the native behavior, including support for a callback and an optional context for this.

Approach

Define the method on Array.prototype. For each element, call the callback with the correct arguments and bind this to the context.

Code

1
2
3
4
5
6
7
8
Array.prototype.forEach = function(callback, context) {
  for (let i = 0; i < this.length; ++i) {
    // Only call for own properties (skip holes in sparse arrays)
    if (Object.prototype.hasOwnProperty.call(this, i)) {
      callback.call(context, this[i], i, this);
    }
  }
};

Complexity

  • ⏰ Time complexity: O(n)
  • 🧺 Space complexity: O(1)