HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Stack implementation in ES6

Submitted by: @import:stackexchange-codereview··
0
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:

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 just return 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 reverseArrayGenerator generator function not in Utils?



  • isDefAndNotNull, while nice, can be shortened or completely dropped. Shortened to object != null which 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.