// Arrays are objects with numerical keys and a length property
// FANCY OBJECTS
const arr = []
typeof arr // "object"
const friendsArray = ['Jake', 'Jordyn', 'Mikenzi']
const friendsObj = {0: 'Jake', 1: 'Jordyn', 2: 'Mikenzi'}
friendsArray[1] // Jordyn
friendsObj[1] // Jordyn
// Create array function
function array() {
// array needs to return an object with a length property that delegates to array.prototype (where we'll be putting all methods)
let arr = Object.create(array.prototype);
// arr.length = 0;
// Specify the length property as non-enumerable (bc of the for in loop used in the filter method)
Object.defineProperty(arr, 'length', {
value: 0,
enumerable: false,
writable: true
})
// Accept 'n' amount of arguments and add those numerical properties onto the object
for (key in arguments) {
arr[key] = arguments[key];
arr.length += 1;
}
return arr;
}
const friends = array('Jake', 'Mikenzi', 'Jordyn')
friends[0] // Jake
friends[2] // Jordyn
friends.length // 3
// Add methods to the array prototype
array.prototype.push = function(element) {
// 'this' references whatever instance called the specific method
this[this.length] = element
this.length++;
return this.length;
}
array.prototype.pop = function() {
this.length--;
const elementToRemove = this[this.length]
delete this[this.length];
return elementToRemove;
}
array.prototype.filter = function(cb) {
// Create new array
let result = array();
// loop over every key/value pair in the array.
// LOOPS OVER ALL "ENUMERABLE" properties of an object, which means 'length' as defined in our "array" object as an enumerable property, which we don't want to count below in the for in loop
for (let index in this) {
if (this.hasOwnProperty(index)) { // Avoid prototype methods
const element - this[index];
if (cb(element, index)) { // if result of invocation is truthy, push the element to the result array
result.push(element)
})
}
}
return result
}