Skip to content

Instantly share code, notes, and snippets.

@aquaductape
Last active June 27, 2019 07:25
Show Gist options
  • Save aquaductape/d35352ba6a5c1993d90a2b4a456358e3 to your computer and use it in GitHub Desktop.
Save aquaductape/d35352ba6a5c1993d90a2b4a456358e3 to your computer and use it in GitHub Desktop.
emulating forEach 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, 'myForEach', {
// if the callback is an arrow function then context will be set to outer scope regardless of providing context argument
// On the other hand if callback is a regular function expression, if context is not provided then the 'this'
// will be set to window(or undefined if strict) since the where the callback function is invoked, it is not an object property,
// but rather just a function pattern --> https://stackoverflow.com/a/2752318/8234457
// tldr; The 'this' keyword’s value has nothing to do with the function itself,
// it's how the function is called determines 'this's value
value: function(callback, context) {
if (typeof callback !== 'function') {
throw new TypeError(`${callback} is not a function`);
}
const length = this.length;
for (let i = 0; i < length; i++) {
// check sparse arrays(holes i.e. non-existing properties) ex. [1, , ,2]
if (i in this) {
callback.apply(context, [this[i], i, this]);
}
}
},
});
// class alternative, safe since methods are locally scoped
class MyMethods {
constructor() {}
forEach(arr, callback, context) {
if (typeof callback !== 'function') {
throw new TypeError(`${callback} is not a function`);
}
const length = arr.length;
for (let i = 0; i < length; i++) {
// check sparse arrays ex. [1, , ,2]
if (i in arr) {
callback.apply(context, [arr[i], i, arr]);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment