Home > Mobile >  Using a class for stacks vs using the built in JavaScript pop() and push() methods
Using a class for stacks vs using the built in JavaScript pop() and push() methods

Time:01-25

I'm working on some algorithms that require me to manipulate data inside a stack, they gave me a class where they defined 3 methods

.pop() which pops the top value of the stack

.push() which pushes a value on to the stack

.peek() which shows me the top value of the stack without modifying the stack

but i don't understand what the difference would be of using the methods in this class versus using the already built in JavaScript methods of push() and pop(), and only having to define .peek() in this class

below is the class stack they gave me as well as an algorithm example used to count the values in the stack, if I am missing any information please let me know and I will update the question to try and make it more clear

class Stack {

  constructor(...values) {

    const data = {};
    let index = 0;

    this.push = function(value) {
      if (arguments.length < 1) {
        throw new TypeError('stack.push() requires a value argument');
      }
      if (typeof value === 'undefined') {
        throw new TypeError('stack.push(value) received undefined');
      }
      data[index] = value;
      index  ;
    };

    this.pop = function() {
      const last = index - 1;
      if (last < 0) return;
      const value = data[last];
      delete data[last];
      index = last;
      return value;
    };

    this.peek = function() {
      const last = index - 1;
      if (last < 0) return;
      return data[last];
    };

    this.print = function() {
      if (index === 0) {
        return 'Stack { <empty> }';
      }
      let output = ' }';
      let last = index - 1;
      for (; last > 0; last--) {
        output = ' <- '   JSON.stringify(data[last])   output;
      }
      output = JSON.stringify(data[last])   output;
      return 'Stack { '   output;
    };

    for (let i = 0; i < values.length; i  ) {
      this.push(values[i]);
    }

    Object.freeze(this);
  }
}

function countValues(stack) {
  let count = 0;
  while (true) {
    if (stack.pop() === undefined) {
      break;
    }
    count  ;
  }

  return count;
}

CodePudding user response:

While the in-built Array pop() and push() methods are most likely faster, the project you are working defines data as an Object and not an Array, so the methods have to be defined from scratch. Making data an Array seems more intuitive to me, but there may be a reason it is an Object instead.

CodePudding user response:

The reason for defining your own class is for abstraction purposes. Even though Array has push() and pop() methods, it's not actually a stack.

If you use an array directly, you can call other methods that aren't supposed to be part of the Stack interface. You can also use direct array indexing. The Stack class forces you to limit your operations to those defined by the class.

Defining a class allows you to change the implementation design. For instance, instead of using an array internally you could use a linked list.

Defining a class allows you to add additional methods like print(), without worrying about conflicts with methods that are defined on the built-in Array class.

CodePudding user response:

Generally is better to use built in Javascript API, specially if the API is implemented in native code (as Arrays are). This Stack class is using a plain object to store the data and, due to this, has pretty much worse performance than even an hypothetical new Stack class wrapping an internal Array and delegating behaviour to the Array API (narrowing the Array interface to match a "Stack"). Objects and Arrays are implemented different in javascript engines, Arrays are way faster than objects. You can modify the current class to just wrap an internal array and expose only the methods you'd see in a Stack interface (and implementing your .peek() method as it doesn't exists in the original API).

Side note: The way the class is implemented is "valid" syntax, but not optimal. If you're going to use ES6 (class keyword instead of constructor functions), better adopt full syntax, defining the instance methods outside the constructor, as it should be, and also defining the fields in instance level, not scoping it only inside the constructor.

  • Related