Reimplement the Built-ins, Arrays and Objects
Objectives
This chapter introduces no new concepts. More built-ins to rebuild yourself, this time working with arrays and objects instead of strings.
Challenge 1: indexOf
Write a function indexOf(arr, val) that returns the first index at which val appears in arr, or -1 if it never appears.
Example:
let arr = [5, 10, 15, 20];
indexOf(arr, 20); // 3
let arr2 = [1, 2, 3, 4, 5];
indexOf(arr2, 2); // 1
let arr3 = [1, 2];
indexOf(arr3, 10); // -1
Constraint: don’t use the built-in Array.indexOf().
Hint: loop through the array by index, and return as soon as you find a match. If the loop finishes without one, that’s your -1 case.
Challenge 2: lastIndexOf
Write a function lastIndexOf(arr, val) that returns the last index at which val appears in arr, or -1 if it never appears.
Example:
lastIndexOf([1, 2, 3, 4], 2); // 1
lastIndexOf([1, 2, 3, 4, 2], 2); // 4
lastIndexOf([1, 2, 3, 4], 22); // -1
Constraint: don’t use the built-in Array.lastIndexOf().
Hint: you can’t stop at the first match this time, so keep going through the whole array and just remember the most recent index where you saw a match.
Challenge 3: max
Write a function max(arr) that returns the highest value in arr.
Example:
max([5, 1, 4, 7, 1, 2]); // 7
max([3, 4, 12, 1, 8]); // 12
max([-1, 6, 3, 2.2, -10, -4]); // 6
Constraint: don’t use the built-in Math.max().
Hint: start by assuming the first element is the biggest, then walk the rest of the array comparing each value against your current best.
Challenge 4: min
Write a function min(arr) that returns the lowest value in arr.
Example:
min([5, 1, 4, 7, 1, 2]); // 1
min([-1, 6, 3, 2.2, -10, -4]); // -10
Constraint: don’t use the built-in Math.min().
Hint: same idea as max, just flip the comparison.
Challenge 5: slice
Write a function slice(arr, start, end) that returns a new array containing the elements of arr from index start up to (but not including) index end. If end is left off, slice all the way to the end of the array. If end is greater than the array’s length, treat it as if it were the array’s length.
Example:
slice([1, 2, 3, 4, 5], 0, 2); // [1, 2]
slice([1, 2, 3, 4, 5], 2, 4); // [3, 4]
slice([1, 2, 3, 4, 5], 2); // [3, 4, 5]
slice([1, 2, 3, 4, 5], 2, 10); // [3, 4, 5]
Constraint: don’t use the built-in Array.slice().
Hint: figure out what the real ending index should be first (handling the missing argument and the too-large argument), then build the result with a loop from start up to that ending index.
Challenge 6: countValues
Write a function countValues(arr, val) that returns how many times val appears in arr.
Example:
countValues([4, 1, 4, 2, 3, 4, 4], 4); // 4
countValues([4, 1, 4, 2, 3, 4, 4], 100); // 0
countValues([], 1); // 0
Hint: a running total that increases by one every time you see a match is all this needs.
Challenge 7: keys
Write a function keys(obj) that returns an array of all the property names in obj.
Example:
let obj = { a: 1, b: 2, c: 3 };
keys(obj); // ["a", "b", "c"]
let obj2 = { first: "Jordan", last: "Reyes" };
keys(obj2); // ["first", "last"]
let obj3 = {};
keys(obj3); // []
Constraint: don’t use the built-in Object.keys().
Hint: for...in loops over an object’s property names directly, no need to touch the values at all.
Challenge 8: values
Write a function values(obj) that returns an array of all the property values in obj.
Example:
let obj = { a: 1, b: 2, c: 3 };
values(obj); // [1, 2, 3]
let obj2 = { first: "Jordan", last: "Reyes", isDogOwner: true };
values(obj2); // ["Jordan", "Reyes", true]
let obj3 = {};
values(obj3); // []
Constraint: don’t use the built-in Object.values().
Hint: this is nearly the same loop as keys, you just look up obj[key] before pushing instead of pushing the key itself.
Challenge 9: entries
Write a function entries(obj) that returns an array of [key, value] pairs, one for each property in obj.
Example:
let obj = { a: 1, b: 2, c: 3 };
entries(obj); // [["a", 1], ["b", 2], ["c", 3]]
let obj2 = { first: "Jordan", last: "Reyes", isDogOwner: true };
entries(obj2); // [["first", "Jordan"], ["last", "Reyes"], ["isDogOwner", true]]
let obj3 = {};
entries(obj3); // []
Constraint: don’t use the built-in Object.entries().
Hint: for each property, build a small two-element array holding the key and its value, then push that pair onto your result array.
Recap
Nine more built-ins rebuilt from scratch, this time array searching and aggregation alongside the three core ways of pulling data out of an object. Same lesson as last time: the loop was always doing the work, the built-in just hid it from you.
Next lesson: array and object puzzles that combine several techniques at once.