Implementing the DOM contains() method

Have tinkered with JavaScript majorly | I like to solve problems on Stack Overflow, write blog articles, create a side project or do something creative.
Search for a command to run...

Have tinkered with JavaScript majorly | I like to solve problems on Stack Overflow, write blog articles, create a side project or do something creative.
I will consider this article as advanced DOM for Node.prototype [native code]. It would take some times to play around with the content for oneself, but overall good job!
Introduction Alright, alright, alright !!! I have officially completed three years at Hashnode now. If you have been following my blog for a while, I have this ritual of documenting what all went in the past year at my job. My general process for do...

Introduction Well here we are reflecting on my time at Hashnode the previous year. I have officially completed two years at Hashnode and as a part of ongoing ritual where I document the experience, here is another one.And also, in first quarter of 20...

Introduction One of the things when using the NextJS ecosystem that hasn't yet clicked for me is their Script component. https://nextjs.org/docs/pages/building-your-application/optimizing/scripts I have been running some experiments on how I can le...

Introduction This article will touch upon scenarios that I have encountered while working at Hashnode where some code reviews helped us prevent future rework on the same issue by having a broader perspective. Code Review 0 The Problem Sometime back,...

Introduction You're scrolling through Twitter (I still like calling it that) or Medium and you get a nice view of the sidebar as it snaps to the bottom or top of the page if you try to scroll beyond its boundaries. We will re-create the same experie...

As per MDN,
The Node.contains() method returns a Boolean value indicating whether a node is a descendant of a given node, i.e. the node itself, one of its direct children (childNodes), one of the children's direct children, and so on.
But wait, Node.prototype.contains(...) already exists. I want another name for our custom function. Let's google synonym of contains coz


Certainly we ain't going with swallow. I think includes would be cool as both Array and String have includes as well in their prototypes.

Before we proceed one important thing to know is that when adding new method to prototype and expecting to use it like so :-
document.includes(document.body),
the method should not be an arrow function so that document can be accessed inside the includes function via this keyword.
Alright then, let's implement Node.prototype.includes in 4 different ways :-

1 Node.prototype.includes = function(node){
2 const currentNode = this;
3 if(!currentNode)
4 return false;
5 if(currentNode===node)
6 return true;
7 let isNodeFound = false;
8 for(let index = 0;index<currentNode.childNodes.length;index++){
9 isNodeFound = isNodeFound || currentNode.childNodes[index].includes(node);
10 if(isNodeFound) return true;
11 }
12 return false;
13 }
Explanation :-
currentNode to this and If currentNode doesn't exist, simply return false.currentNode is equal to node return true.isNodeFound to false. Then loop over childNodes of the currentNode and on each child, call the includes method again to check if they include the node element. If they do, isNodeFound will ultimately become true since it is being Orrrrrrd with the results coming from respective childNodes and reassigned to itself. Once isNodeFound is true, we don't need to loop over rest of the childNodes of currentNode and exit early by returning true else ultimately return false.1 Node.prototype.includes = function (node) {
2 const queue = [];
3 let currentNode = this;
4 queue.push(currentNode);
5 while (queue.length) {
6 currentNode = queue.shift();
7 if (currentNode === node) return true;
8 if (currentNode.hasChildNodes()) {
9 queue.push(...currentNode.childNodes);
10 }
11 }
12 return false;
13 };
Explanation :-
queue. Set currentNode to this and push (or enqueue to be specific) it. queue is not empty, dequeue the currentNode from front of the queue (using shift here). If currentNode is equal to node then return true. Otherwise enqueue the childNodes of currentNode (using push here). Once we are out of the while loop, we have traversed all the nodes and can safely say that we couldn't find the node and return false.Note - The above can be transformed to iterative DFS by using pop instead of shift and obviously for the sake of consistency, rename queue to stack.

Till now both the approaches followed the classic DS/Algo traversal with DFS and BFS. We are now going to see 2 more approaches which take benefit of certain properties that are specifically applicable to DOM nodes.
1 Node.prototype.includes = function (node) {
2 const currentNode = this;
3 if (!currentNode)
4 return false;
5 if (currentNode === node) return true;
6 return !!(currentNode.firstChild?.includes(node) || currentNode.nextSibling?.includes(node))
7 };
Explanation :-
currentNode to this and if currentNode doesn't exist, return false.currentNode is equal to node return truefirstChild includes the node OR current node's nextSibling includes the node. Also notice the !!. That's because I have used the ? operator due to which we can end up with undefined || undefined condition or false || undefined condition where both evaluate to undefined which is a falsy value and so !! will ensure undefined coerces to false. 
1 Node.prototype.includes = function(node){
2 const currentNode = this;
3 while(node){
4 if(currentNode===node) return true;
5 node = node.parentNode;
6 }
7 return false;
8 }
Explanation :-
node exists, we check if currentNode is equal to node and if it is we return true, else the node is made to point to it's parentNode for further comparisons. If we exit the while loop, it's safe to say that the node isn't a contained within the currentNode and thus, return false.
And here is a working codepen with all 4 implementations. Comment the rest for any one to reflect ✨.
Have more ways to implement the same ? Feel free to share your approach in the comment section 👇.