MaxHeap implementation in JavaScript Here is MaxHeap implementation in pure JavaScript:

/**
 * We initialize index 0 because, calculations for finding 
 * children of a node and the parent of a node is easier 
 * parent = [ k/2 ], children: [ k*2, k*2+1 ]
 */
class Heap {
    constructor() {
        this.queue = [0];
    };

    /**
     * Bottom-up reheapify (swim) : If the heap order is violated because a node's key 
     * becomes larger than that node's parents key, then we can make progress 
     * toward fixing the violation by exchanging the node with its parent
     * 
     * @param {Number} k 
     */
    swim(k) {
        while ( k&gt;1 &amp;&amp; this.less(k, Heap.flr(k/2)) ) {
            this.exch(k, Heap.flr(k/2) ) ;
            k = Heap.flr(k/2);
        }
    };

    /**
     * Top-down heapify (sink) :  If the heap order is violated because a node's key becomes 
     * smaller than one or both of that node's children's keys, then we can make progress 
     * toward fixing the violation by exchanging the node with the larger of its two children.
     * 
     * @param {Number} k
     */
    sink(k) {
        while ( 2*k &lt;= this.n() ) {
            const c1 = 2*k; 
            const c2 = 2*k + 1;
            const j = this.more(c1,c2)?c2:c1;

            if (this.more(k, j) ) {
                this.exch(k, j);
            } else {
                break;
            }
            k = j;
        }
    };


    /**
     * 
     * @param {Number} i 
     * @param {Number} j 
     */
    less(i,j) {
        return this.queue[i]&gt;this.queue[j];
    };


    /**
     * 
     * @param {Number} i 
     * @param {Number} j 
     */
    more(i,j) {
        return this.queue[i]&lt;this.queue[j];
    };


    /**
     * 
     * @param {Number} i 
     * @param {Number} j 
     */
    exch(i, j) {
        const tmp = this.queue[i];
        this.queue[i] = this.queue[j];
        this.queue[j] = tmp;
    };

    /**
     * Inserts element into the internal queue
     * @param {Number} k 
     */
    insert(k) {
        this.queue.push(k);
        this.swim(this.n());
    };

    /**
     * Returns max element in the internal queue
     */
    max() {
        if (!this.isEmpty() ) {
            return this.queue[1];
        }
        return false;
    };

    /**
     * Deletes and returns max element from the internal queue
     */
    delMax() {
        if (!this.isEmpty()) {
            const mx = this.queue[1];
            this.queue[1] = this.queue.pop();
            if (!this.isEmpty()) {   
                this.sink(1);
            }
            return mx;
        };
        return false;
    };

    /**
     * Checks for emptyness (here we consider the queue empty if the length of the queue is 1) 
     */
    isEmpty() {
        return this.queue.length === 1;
    };

    /**
     * Returns last element index in the internal queue
     */
    n() {
        return this.queue.length-1;
    };

    /**
     * in JS dividing odd number by even number gives fraction not integer, 
     * we need to get rid of this part
     * @param {Number} i 
     */
    static flr(i) {
        return Math.floor(i);
    }
}


Is the implementation correct? What are the shortcomings that can be fixed?
Bug

There's a bug in delMax:


const mx = this.queue[1];
this.queue[1] = this.queue.pop();
if (!this.isEmpty()) {   
    this.sink(1);
}
return mx;



What will happen when the heap has 1 element? The code will:


Replace the first element with itself (the last element)
It doesn't become empty


In other words, the last element cannot be deleted.

Avoid hacky solutions

This code happens to work, but it's hacky:


while ( 2*k &lt;= this.n() ) {
    const c1 = 2*k; 
    const c2 = 2*k + 1;
    const j = this.more(c1,c2)?c2:c1;



What's wrong with it? When 2*k == this.n(), then c2 will point past the end of the queue, and more will compare queue[c1] with undefined, and always return false. The code works, but it would be better to not rely on numeric comparisons with undefined.

Look for generalization opportunities

It's a good idea to use a function to decide the ordering of elements, similar to what you did with less and more. This could open the opportunity to make the implementation work with arbitrary ordering.

The current implementation doesn't make it easy to pass in these functions to customize the behavior. It would be good to make that possible. And it would be even better to make it work with a single function, let's say less.

If you do that, then you should rename some methods, since max and delMax won't make sense for a min-heap ordering. You could rename these to peek and pop.

Hide implementation details

The class exposes many methods that are unnecessary for users:
swim, sink, less, more, exch, flr.
These are implementation details, and it would be best to hide them.

Drop the unnecessary trick

This trick:


/**
 * We initialize index 0 because, calculations for finding 
 * children of a node and the parent of a node is easier 
 * parent = [ k/2 ], children: [ k*2, k*2+1 ]
 */



Looks completely unnecessary... I don't see a reason whatsoever why the dummy first element helps. You can eliminate it, and the implementation will be simpler and clearer.

Dividing by 2

I'm not sure if this is recommended in JavaScript world,
but instead of Math.floor(x / 2),
x &gt;&gt; 1 feels cleaner.

Naming

Some method names could be improved:


exch -> swap
n -> size
insert -> add
flr -> floor, or instead of always calling it with flr(k / 2) you could name it childIndex and call it with k, letting it do the necessary math
flr uses parameter i. The name i is best in simple counting loops.