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.