Skip to content

Instantly share code, notes, and snippets.

@aquaductape
Last active July 4, 2019 08:58
Show Gist options
  • Save aquaductape/aa992b96ed2fb0fccef5af1f40a4e63d to your computer and use it in GitHub Desktop.
Save aquaductape/aa992b96ed2fb0fccef5af1f40a4e63d to your computer and use it in GitHub Desktop.
emulating map method
// Array prototype method, however this is not safe, since it is added to the global scope
// definedProperty makes method non-enumerable as well as adding new property to in this case, to Array prototype
Object.defineProperty(Array.prototype, 'myMap', {
// if callback is arrow function then context will be set to outer scope regardless of providing context argument
value: function(callback, context) {
'use strict';
// will context to undefined if it is global object
if (typeof callback !== 'function') {
throw new TypeError(`${callback} is not a function`);
}
const length = this.length;
let newArr = [];
if (context !== undefined) {
for (let i = 0; i < length; i++) {
// check sparse array ex. [1, , ,2]
if (i in this) {
// call is faster than apply
newArr[i] = callback.call(context, this[i], i, this);
// not using push in case the array has empty slots
// it's not possible to push empty slot https://stackoverflow.com/questions/56659890/possible-to-push-empty-slot-to-an-array
// Instead I'm setting the index of the array to a value,
// once a valid key/index is found after the empty slot,
// the new result will be added at that specific index,
// and previous uninitialized indices will be set to empty
}
}
} else {
// increase performance if there is no context or is window object
for (let i = 0; i < length; i++) {
if (i in this) {
newArr[i] = callback(this[i], i, this);
}
}
}
// in case the whole array is sparse or last item is empty
newArr.length = length;
return newArr;
},
});
// class alternative, safe since methods are locally scoped
class MyMethods {
constructor() {}
map(arr, callback, context) {
if (typeof callback !== 'function') {
throw new TypeError(`${callback} is not a function`);
}
const length = arr.length;
const newArr = [];
for (let i = 0; i < length; i++) {
if (i in arr) {
newArr[i] = callback.apply(context, [arr[i], i, arr]);
}
}
if (newArr.length < length) {
newArr.length = length;
}
return newArr;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment