Search code examples
javascriptstack-overflow

Stack Overflow With JavaScript Filter Function


Hey guys I was trying to mimic an array with an object in JavaScript. I thought it would be easy to mimic the length function with a getter but it looks like my filter function is leading to a stack overflow. For some reason I can't figure out what is going wrong. Can you spot the error?

const o = {
  0: 'hello',
  1: 'there',
  fakeLen: () => {
    return Object.keys(this).length
  },
  get length() {

    const keys = Object.keys(this);
    const filtered = keys.filter(key => typeof this[key] != 'function');
    console.log('filtered array ', filtered);
    return filtered.length;
  }

};

console.log('correct?  ', o.length);
console.log('wrong? ', o.fakeLen());

Maybe I am just tired but I don't see how a filter function can lead to a stack overflow!


Solution

  • When you invoke the Object.keys() method on this, you're going to get all the properties inside your object, so keys will look like:

    ["0", "1", "fakeLen", "length"]
    

    Then, when you filter each key, you use bracket notation on each element in the above array. So, you will do the following:

    typeof this["length"] != 'function'
    

    Because length is a getter (due to get), the this["length"] will cause your length method to be called again, thus repeating the process until you get a stack overflow.

    const o = {
      get length(){
        this["length"];
      }
    };
    
    o.length

    You can either make your length property non-enumerable (as shown by Medet Tleukabiluly), so that when you invoke Object.keys() on it, it won't appear in your keys list, or, you could simply remove "length" from your keys before filtering:

    const o = {
      0: 'hello',
      1: 'there',
      get length() {
        const keys = Object.keys(this).filter(key => key !== "length");
        const filtered = keys.filter(key => typeof this[key] != 'function');
        return filtered.length;
      }
    
    };
    
    console.log(o.length);