Переполнение стека с функцией фильтра JavaScript - PullRequest
1 голос
/ 15 октября 2019

Эй, ребята, я пытался имитировать массив с объектом в JavaScript. Я думал, что было бы легко имитировать функцию длины с помощью геттера, но похоже, что моя функция фильтра приводит к переполнению стека. По какой-то причине я не могу понять, что происходит не так. Можете ли вы определить ошибку?

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());

Возможно, я просто устал, но я не понимаю, как функция фильтра может привести к переполнению стека!

Ответы [ 2 ]

2 голосов
/ 15 октября 2019

Когда вы вызываете метод Object.keys() для this, вы получите все свойства внутри вашего объекта, поэтому keys будет выглядеть так:

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

Затем, когда выфильтруя каждый ключ, вы используете скобочные обозначения для каждого элемента в приведенном выше массиве. Итак, вы будете делать следующее:

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

Поскольку length является геттером (из-за get), this["length"] вызовет повторный вызов вашего length метода, повторяя таким образомпроцесс, пока вы не получите переполнение стека.

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

o.length

Вы можете сделать ваше свойство length не перечисляемым (как показано Медетом Тлекабилулы), так что когда вы вызываете Object.keys(), оно не будетпоявится в вашем списке keys, или вы можете просто удалить "length" из ваших ключей перед фильтрацией:

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);
1 голос
/ 15 октября 2019

Правильный путь

const o = {
  fn: function () {},
  0: 'hello',
  1: 'there',
  fakeLen: function() { // NOT ARROW FN
    return Object.keys(this).length
  }
};
// define getter
Object.defineProperty(o, 'length', {
  enumerable: false,
  get: function() {
    const keys = Object.keys(this);
    const filtered = keys.filter((key) => {
      console.log(this[key], typeof this[key])
      return typeof this[key] !== 'function'
    });
    console.log('filtered array ', filtered);
    console.log('filtered.length', filtered.length)
    return filtered.length;
  }
})

console.log('length  ', o.length);
console.log('fakeLen ', o.fakeLen());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...