-
-
Save alexhawkins/28aaf610a3e76d8b8264 to your computer and use it in GitHub Desktop.
'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 |
How can we check other methods on our own? How to find JS build in methods definitions?
You can solve that problem by doing
if (i in this)
callback(this[i], i, this);
That way, since each array element's index is a property of the array, indices 3-9 won't result in undefined being printed
@fuermosi777 or we can abstract it to
if(!accumulator)
Awesome work!!
Many native array functions, including Array.map and Array.filter, are therefore written as pure functions. They take in an array reference and internally, they copy the array and work with the copy instead of the original.
https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0
nice work but this isn't it
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
the polyfill here does it
thank you very much!!
Thanks for that, very easy to understand the behaviour, instead of reading a big document
Its really useful bro....
good job done!
Very useful!!
This goes to confirm this article javascript performance mistakes . Its more helpful to use the plain old for loop than the new array functions in es6.
Cool! Been looking for this for a while.
@alexhawkins How do you use context
in myFilter and why does your solution work when context
is undefined as it is in your tests.
@usmanajmal someFunction.call()
, aka Function.prototype.call()
, uses its first argument as "this
". That means that callback.call(context, ...)
is a direct equivalent to callback.bind(context)(...)
, which in turn says that any instances of this
within callback
will refer to context
.
As you can probably tell, it has little to no relevance here... so TBQH I'm not quite sure why this gist's author used .call()
in such a manner. Rather than defining myFilter(callback, context)
and then doing callback.call(context, ...)
, it would be much preferable (as far as I can tell) to define myFilter(callback)
and simply do callback(...)
; if the user needs to bind to context
, they can pass the callback in as callback.bind(context)
without forcing the myFilter function to care about it.
(Same goes for myReduce()
... would be simpler within it to do callback(...)
rather than callback.call(undefined, ...)
.)
Wow.. You made it look so easy !! GREAT
Good work, thanks!
what has "callback(this[i], i, this)"; have to do in the code??
thanks,
Can you explain how Map
data structure is implemented in JS, Considering Non-Primitive data type as key.
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
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;
}
Thanks for helping us out! Great one!
Seriously Great one ☝️. Thanks!
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;
};
Good work, thanks!
Very nice
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;
};
@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..."})`
line 66: why not just let accumulator = initialValue?