#Javascript Basics
In this exercise, we'll use JS objects and prototypes, play with the Document Object Model (DOM), and get used to some functional patterns in JS.
Do the first few exercises in Functional Javascript RebootU exercises, at least up until ("Basic: Reduce").
Optionally, you may also find it useful to complete the Planet Proto workshopper.
We're going to add some functionality to the Array.prototype object, as well as create some new tools to use with the DOM. In the below items, you should never find it necessary to use a loop, but instead should rely on Array.prototype methods such as .forEach(), .filter(), .some() and so on.
Place your code for these items in Array.prototype-extensions.js in the js directory. You may test in any number of ways, including temporarily adding tests to your file and running them at the command line using node, or by building a test HTML file.
- To get warmed up, let's implement a non-mutating array sort method. Array.prototype.sort mutates the given array. Let's create a new method on Array.prototype (so it will be available to all array objects) called
orderthat returns a sorted copy of an array (hint: first clone the array, and then call the built-in sort method). It should have the same sytnax assort:arr.order([compareFunction]). - Array.prototype.includes is an experimental feature of JS (part of the ECMASript 7 proposal and not supported by most browsers). Let's create a polyfill that provides this functionality. You may noticed that there's a polyfill in the above-linked reference, but you should obviously build your own. It need not conform to the exact same edge-case behaviors, or use the same approach, but it should reasonably handle empty arrays and non-array input.
- Similarly, Array.prototype.find isn't well supported (it's part of the ECMAScript 6 proposal). Implement this method too, using the same outlined behavior at the above reference.
- Let's also implement an Array.prototype.findAll method, which should work similarly to
Array.prototype.findbut return an array of values. - Finally, let's make our code future-proof. When these specs are implemented, we won't want our code to override the browser implementations, so add checks before each method definition to ensure that if the method already exists, we don't override it.
Place your code for these items in DOMUtils.js in the js directory. There is a file named test.html that you can use to test your code, and may modify as you like.
For each of these, we'll be implementing some utility methods to do varios things with the DOM. In your file, create an object literal named DOMUtils (this can live in the global namespace) to add the methods to. This will effectively namespace our methods.
- Implement
DOMUtils.flattenDOM([node]), which should return an array containing each node below the given node (includingnodeitself), and should default todocument.body.parentNodeifnodeis not provided. Look intoParentNode.childrenfor a starting tip. (Note: You may also see a Node.childNodes property floating around. Don't use it. It differs from ParentNode.children and some important ways.) The method should throw an exception of the argument is not an actual DOM node. To check this, you'll need to use theinstanceofoperator with the appropriate constructor name (cough cough). - Impelement
DOMUtils.getIds([node]), which should return an array of unique strings corresponding to all DOM node IDs attached to nodes belownode(again, this should be inclusive ofnode, withnodedefaulting todocument.body.parentNodeif not provided). This method should thrown an exception as specified in 1. - Implement
DOMUtils.getClasses([node]), which should return an array of unique strings corresponding to the values of allclassattributes attached to nodes belownode. This method should throw an exception as specified in 1. - Bonus: Make 2 and 3 "live" methods, such that the returned array has elements added and removed as the DOM changes. If you want some hints on how to do this, ask me.
When you're done, commit and push all of your work and email me.