Skip to content

Instantly share code, notes, and snippets.

@alexhawkins
Last active February 2, 2024 16:57
Show Gist options
  • Save alexhawkins/28aaf610a3e76d8b8264 to your computer and use it in GitHub Desktop.
Save alexhawkins/28aaf610a3e76d8b8264 to your computer and use it in GitHub Desktop.
Implementation of Native JavaScript Methods (forEach, Map, Filter, Reduce, Every, Some)
'use strict';
/*****************NATIVE forEACH*********************/
Array.prototype.myEach = function(callback) {
for (var i = 0; i < this.length; i++)
callback(this[i], i, this);
};
//tests
var arr = ['biggy smalls', 'bif tannin', 'boo radley', 'hans gruber'];
arr.myEach(function(word) {
console.log(word);
});
//biggy smalls
//bif tannin
//boo radley
//hans gruber
/*****************NATIVE MAP*************************/
Array.prototype.myMap = function(callback) {
arr = [];
for (var i = 0; i < this.length; i++)
arr.push(callback(this[i], i, this));
return arr;
};
//tests
var arrs = ['dic tanin', 'boo radley', 'hans gruber'];
var numbers2 = [1, 4, 9];
var goodT = arrs.myMap(function(n) {
return n;
});
var squareRoot = numbers2.myMap(function(num) {
return Math.sqrt(num);
});
console.log(goodT); // [ 'dic tanin', 'boo radley', 'hans gruber' ]
console.log(squareRoot); // [ 1, 2, 3 ]
/*****************NATIVE FILTER*************************/
Array.prototype.myFilter = function(callback, context) {
arr = [];
for (var i = 0; i < this.length; i++) {
if (callback.call(context, this[i], i, this))
arr.push(this[i]);
}
return arr;
};
//tests
var numbers = [1, 20, 30, 80, 2, 9, 3];
var newNum = numbers.myFilter(function(n) {
return n >= 10;
});
console.log(newNum); // [ 20, 30, 80 ]
/*****************NATIVE REDUCE*************************/
Array.prototype.myReduce = function(callback, initialVal) {
var accumulator = (initialVal === undefined) ? undefined : initialVal;
for (var i = 0; i < this.length; i++) {
if (accumulator !== undefined)
accumulator = callback.call(undefined, accumulator, this[i], i, this);
else
accumulator = this[i];
}
return accumulator;
};
//tests
var numbers3 = [20, 20, 2, 3];
var total = numbers3.myReduce(function(a, b) {
return a + b;
}, 10);
console.log(total); // 55
var flattened = [
[0, 1],
[2, 3],
[4, 5]
].reduce(function(a, b) {
return a.concat(b);
});
console.log(flattened); //[ 0, 1, 2, 3, 4, 5 ]
/*****************NATIVE EVERY*************************/
Array.prototype.myEvery = function(callback, context) {
for (var i = 0; i < this.length; i++) {
if (!callback.call(context, this[i], i, this))
return false;
}
return true;
};
//tests
var passed = [12, 5, 8, 130, 44].myEvery(function(element) {
return (element >= 10);
});
console.log(passed); // false
passed = [12, 54, 18, 130, 44].myEvery(function(element) {
return (element >= 10);
});
console.log(passed); // true
passed = [12, 54, 18, 130, 44].myEvery(function(element) {
return (element >= 13);
});
console.log(passed); // false
/*****************NATIVE SOME*************************/
Array.prototype.mySome = function(callback, context) {
for (var i = 0; i < this.length; i++) {
if (callback.call(context, this[i], i, this))
return true;
}
return false;
};
//tests
var passed = [12, 5, 8, 130, 44].mySome(function(element) {
return (element >= 200);
});
console.log('some: ' + passed); //some: false
var passed = [12, 5, 8, 130, 44].mySome(function(element) {
return (element >= 100);
});
console.log('some: ' + passed); //some: true
@priyankamalviya
Copy link

everything looks great except, in reduce, why do we need all these parameters when we are binding the reduceFn context? [undefined, accumulator, this[i], i, this]? Any explanations please? I noticed, this breaks without the undefined

@NexGenUA
Copy link

NexGenUA commented Oct 4, 2019

myReduce function is wrong

[undefined,null,'3',4,5].reduce((acc, cur) => acc*cur) // NaN; 
[undefined,null,'3',4,5].myReduce((acc, cur) => acc*cur) // 0;

correct:

Array.prototype.myReduce = function(...rest) {
  
  if (!rest || typeof rest[0] !== 'function') {
    throw new TypeError(`${rest[0]} is not a function`);
  }

  const callback = rest[0];
  const arr = this;
  let thumb = rest.length > 1;
  let accumulator = thumb ? rest[1] : arr[0];

  for (let i = 0; i < arr.length; i++) {
    if (thumb) {
      accumulator = callback(accumulator, arr[i], i, arr);
    } else thumb = true;
  }
  return accumulator;  
}

@vihangmi10
Copy link

Thanks for helping us out! Great one!

@abhijithsreenivas
Copy link

Seriously Great one ☝️. Thanks!

@jialihan
Copy link

jialihan commented Mar 7, 2021

My reduce implement: just a little bit difference:

Array.prototype.myReduce = function (fn, initialValue) {
    var accumulator = initialValue || this[0];
    for (var i = 0; i < this.length; i++) {
        if (!initialValue && i === 0) {
            // when initialValue is not provided
            continue;
        }
        accumulator = fn.call(null, accumulator, this[i], i, this);
    }
    return accumulator;
};

@mAminP
Copy link

mAminP commented Aug 27, 2021

Good work, thanks!

@hs2504785
Copy link

Very nice

@bookuha
Copy link

bookuha commented Sep 1, 2022

else
accumulator = this[i]; at line 70
is not like this in current native reduce,
this one will omit undefined values at any step and proceed to this[i]
the native one will sum it up, it will use this check for initial value just once

Thank you!

Array.prototype.myReduce = function(callback, initialVal) {
   
    if(initialVal !== undefined) accumulator = initialVal;
    else accumulator = this[i++];
        
    for (var i = 0; i < this.length; i++) {
            accumulator = callback.call(undefined, accumulator, this[i], i, this);
    }
    return accumulator;
};

@VladSemenik
Copy link

VladSemenik commented Feb 2, 2024

@alexhawkins Bro, what will happen to your methods which are binding context if you pass arrow function () => {}. I do think it is not gonna work.

I deleted my smiles because I thought specific bug in your implementation, but js filter works as same as yours. So I guess thats why none uses it. 😅 This one I had to add.

`Array.prototype.myFilter = function(callback, context) {
arr = [];
for (var i = 0; i < this.length; i++) {
if (callback.call(context, this[i], i, this))
arr.push(this[i]);
}
return arr;
};

[].myFilter.call([1,2,3], (e) => {
console.log(this.isItWorking)
return e % 2 === 0
}, {isItWorking: "mmmm..."})`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment