patternjavascriptMinor
Stack implementation in ES6
Viewed 0 times
implementationes6stack
Problem
Finally happy to see that now we can have iterators and generators. I also need to try to have private properties too so that we have well encapsulated data structures and I see that there are Proxies and Symbols which could help me do that.
Utils:
Code:
Test:
```
import {strictEqual as equal} from "assert";
import Stack from "../src/Stack";
suite("Stack", () => {
test("without iterator", () => {
const s = new Stack();
s.push(1);
equal(s.size(), 1);
equal(s.pop(), 1);
equal(s.size(), 0);
});
test("with iterator", () => {
let s = new Stack([1, 2, 3]);
equal(s.size(), 3);
s = new Stack('hello');
equal(s.size(), 5);
s = new Stack([{name: 'Foo'}, {name: 'Bar'}]);
equal(s.size(), 2);
});
test("peek", () => {
let s = new Stack([1, 2, 3]);
equal(s.peek(), 3);
s.pop();
equal(s.peek(), 2);
});
test("iterator", () => {
const s = new Stack([1, 2, 3]);
let i = 3;
Utils:
export const isDefAndNotNull = object =>
object !== undefined && object !== null;
export const isIterable = object =>
isDefAndNotNull(object) && typeof object[Symbol.iterator] === 'function';Code:
import {isDefAndNotNull, isIterable} from "./Utils";
function *reverseArrayGenerator(arr) {
let i = arr.length;
while(--i >= 0) {
yield arr[i];
}
}
const data = Symbol("data");
export default class {
constructor(iterable) {
this[data] = [];
if (isIterable(iterable)) {
for (let item of iterable) {
this.push(item);
}
}
}
peek() {
return this[data].slice(-1)[0];
}
push(item) {
this[data].push(item);
}
pop() {
return this[data].pop();
}
isEmpty() {
return this[data].length === 0;
}
size() {
return this[data].length;
}
toString() {
let res = [];
for (let item of this) {
res.push(item);
}
return JSON.stringify(res.join(' '));
}
[Symbol.iterator]() {
return reverseArrayGenerator(this[data]);
}
}Test:
```
import {strictEqual as equal} from "assert";
import Stack from "../src/Stack";
suite("Stack", () => {
test("without iterator", () => {
const s = new Stack();
s.push(1);
equal(s.size(), 1);
equal(s.pop(), 1);
equal(s.size(), 0);
});
test("with iterator", () => {
let s = new Stack([1, 2, 3]);
equal(s.size(), 3);
s = new Stack('hello');
equal(s.size(), 5);
s = new Stack([{name: 'Foo'}, {name: 'Bar'}]);
equal(s.size(), 2);
});
test("peek", () => {
let s = new Stack([1, 2, 3]);
equal(s.peek(), 3);
s.pop();
equal(s.peek(), 2);
});
test("iterator", () => {
const s = new Stack([1, 2, 3]);
let i = 3;
Solution
- Why are you using a symbol for the data? If you're hoping for private variables, you're out of luck.
return JSON.stringify(res.join(' '));Why? Why not justreturn JSON.stringify([...this])or something? Why both join into a string and JSON stringify?
return this[data].slice(-1)[0];is inefficient as it needlessly copies the array for each call.return this[data][this.size()];should be (if marginally) better.
- Why is your
reverseArrayGeneratorgenerator function not in Utils?
isDefAndNotNull, while nice, can be shortened or completely dropped. Shortened toobject != nullwhich is exactly the same thing, or dropped altogether in favor of:object && typeof object[Symbol.iterator] === 'function';
I won't repeat what the other answer says, but it's also correct.
Context
StackExchange Code Review Q#135459, answer score: 2
Revisions (0)
No revisions yet.