January 25, 2020
I am currently diving into my first job search as a software engineer, and recently had a mock technical interview. The interview was done in JavaScript, and consisted of two questions. The first was a fairly standard algorithm question, but the second was quite interesting: I was asked to build the document.getElementByClassName
method from scratch, as if it didn’t exist. I found it enlightening to build out a method that I had used so many times before, and improved my understanding of both DOM manipulation and JavaScript as a whole. In this article I will walk you through the solution I came up with.
The goal is to create a functionally equivalent version of document.getElementByClassName
. In order to do this, our new function needs to have to following features:
<html><body><div class='parent'><p class='hello'>hello world 1</p><p class='hello'>hello world 2</p><p class='hello'>hello world 3</p><p class='hello'>hello world 4</p></div></body></html>
const parent = document.getElementsByClassName('parent')// => <div class='parent'></div>const helloWorlds = document.getElementsByClassName('hello')// => [ <p class='hello'>hello world 1</p>,// <p class='hello'>hello world 2</p>,// <p class='hello'>hello world 3</p>,// <p class='hello'>hello world 4</p> ]
First, we need to create a conceptual plan for our function:
Based on this plan, we will need to create a recursive helper function, or a function that calls itself within its own definition, to check all elements beneath the primary. We will call this helper function within the main function. The return value of the main function should be an array of elements, which we will declare as an empty array at the top, and add elements to as we move along.
Now that we have a solid plan, let’s get coding!
Here we will define our main function. In the body, we will define two variables: elements
, an array into which all elements with matching class names will be added; firstChildren
, all the children of the element the function is called on. For the latter, we can take advantage of JavaScript’s .children()
method, which returns an HTMLCollection containing all child elements of the node upon which it is called. This HTMLCollection can be treated like an array.
function getElementsByClassName2(classNameStr) {const elements = [] // the array we will add matching elements toconst firstChildren = this.children // all the children of the element the function is called onreturn elements}
A recursive function is a function which calls itself within the definition, while a helper function is a function which abstracts away some code to make it both re-usable and more readable.
function getElementsByClassName2(classNameStr) {function checkChildren(child) {// check if the child has a matching class. If so, push the the elements arrayif (child.classList.contains(className)) {elements.push(child)}// check if that child has children of its own. If so, call checkChildren one each childif (child.children) {const children = child.childrenchildren.forEach(checkChildren)}}}
Now we want to call the checkChildren
method on each of the firstChildren
. After this function runs, our elements array should contain all of the matching elements!
function getElementsByClassName2(classNameStr) {const elements = []const firstChildren = this.childrenfunction checkChildren(child) {if (child.classList.contains(className)) {elements.push(child)}if (child.children) {const children = child.childrenchildren.forEach(child => checkChildren(child))}}// call the checkChildren method on the firstChildrenfirstChildren.forEach(child => {checkChildren(child)})return elements}
Finally, in order for us to be able to call this function on any HTML Element, we need to add it to the HTML element prototype.
HTMLElement.prototype.getElementsByClassname2 = getElementsByClassName2
And just like that, we are done! Our new method getElementsByClassName2
now has the same functionality as the original getElementsByClassName
. I hope you found this process as interesting and informative as I did!
If you enjoyed the article, feel free to follow me here or on twitter @shane__lonergan
The personal blog of Shane Lonergan. NYC based software engineer, actor, director, and musician. Documenting my journey from the stage to the computer screen. To keep up to date, you should follow me on Twitter.