Simple Stack Implementation in JavaScript

I was looking through some C# docs, and I realized that there isn’t a Stack implementation in JavaScript. While a stack can mostly be implemented using arrays, it still seems nice to have an actual Stack object. Here is my initial take on it (incorporating some great feedback from @senocular) using arrays under the covers:

class Stack {
    constructor(...items) {
        this.items = items;
    }
    clear() {
        this.items.length = 0;
    }
    clone() {
        return new Stack(...this.items);
    }
    contains(item) {
        return this.items.includes(item);
    }
    peek() {
        var itemsLength = this.items.length;
        var item = this.items[itemsLength - 1];
        return item;
    }
    pop() {
        var removedItem = this.items.pop();
        return removedItem;
    }
    push(item) {
        this.items.push(item);
        return item;
    }
}

Here is how you can use it:

var myStack = new Stack();
myStack.push("One");
myStack.push("Two");
myStack.push("Three!");

myStack.peek(); // Three

var lastItem = myStack.pop();
console.log(lastItem) // Three

myStack.peek(); // Two

I was torn between implementing this as an array vs. using key/value pairs on an Object where the key would be the current item position and the value would be the item I would be adding. Do you all have a preference for one approach over the other?

Cheers,
Kirupa :stuck_out_tongue:

I think using arrays makes the most sense. Some other suggestions I have are:

I would move the cloning to the constructor. This helps prevent mutations on the items list from the original stack source

var myItems = ['One', 'Two', 'Three']
var myStack = new Stack(myItems)
myStack.peek() //-> Three
myItems.push('Four') // <-- orig items, not stack
myStack.peek() //-> Four

Though if you use a rest there instead of an array, that solves the problem as well. Additionally, it means you don’t need to slice in clone, nor use the isArray (bonus points) in the constructor.

// ...
constructor(...items) {
  this.items = items
}
// ...
var myStack = new Stack('One', 'Two', 'Three')
// or
var myItems = ['One', 'Two', 'Three']
var myStack = new Stack(...myItems) // <-- spread for arrays

Arrays also now have a contains - though named includes, so that can simplify the Stack contains.

return this.items.includes(item)

(^ or use with if/else returning true or false. Though it is more verbose, that style of coding does lend itself to be easier to read for those still learning. The includes still wins over indexOf there because comparing against a -1 is in itself a little confusing)

1 Like

I like your suggestions, sen! I failed to take into account that passing arrays around could cause someone to update the contents outside of the Stack. I’ve updated the snippets to reflect that.

:stuck_out_tongue: