Попытка использовать объект запоминания, чтобы проверить, был ли аргумент уже вычислен … похоже, не удается справиться с использованием объектов в качестве аргументов

#javascript #object #callback #closures #memoization

#javascript #объект #обратный вызов #замыкания #запоминание

Вопрос:

Итак, я использую внутреннюю функцию для закрытия и для передачи неизвестного количества аргументов. Предполагается, что функция использует какую-то запоминание (я решил использовать объект), чтобы проверить и посмотреть, были ли результаты выполнения аргументов через обратный вызов уже вычислены и сохранены. Вот функция, которую я написал до сих пор…

 function memoize(func) {
    // Define an object to hold results
    let obj = {}
    // define an inner function for closure that takes an argument
    function inner(...arg) {
        if (obj[arg]) {
            return obj[arg]
        } else {
            obj[arg] = func(...arg);
            return obj[arg];
        }
    }
    return inner;
}
 

Я получаю сообщение об ошибке, что моя функция «должна работать с объектами в качестве аргументов»… В настоящее время я не уверен, почему мой текущий код НЕ БУДЕТ работать с объектами в качестве аргументов… Так что, если бы кто-нибудь мог это объяснить, это было бы с благодарностью. Вот алгоритм, используемый для тестирования моей функции…

 it('should work with objects as arguments', () => {
    const firstTime = timeCheck({ foo: 'bar' });
    wait(5);
    const secondTime = fastTimeCheck({ foo: 'bar' });
    wait(5);
    expect(firstTime).to.not.equal(secondTime);
    expect(fastTimeCheck({ foo: 'bar' })).to.equal(secondTime);
    expect(fastTimeCheck({ foo: 'bar' })).to.not.equal(fastTimeCheck({ different: 'result' }));
  });
 

Если у вас есть время. Я был бы признателен, если бы знал, почему моя текущая функция не работает с объектами в качестве аргументов… Кроме того, как я могу изменить то, что я написал, чтобы удовлетворить алгоритм тестирования.

Комментарии:

1. Ключи объекта должны быть строками, а не объектами.

2. Хорошо, так что именно это означает в моем случае?

3. Это означает, что вы не должны использовать это для функций с аргументами объекта. Или, может быть, вы могли бы изменить ключ на JSON.stringify(arg)

4. Спасибо! Это сработало! Теперь мне просто нужно прочитать об этом и выяснить, почему lol!

Ответ №1:

Имена свойств являются строковыми или символьными. Любое другое значение, включая число, преобразуется в строку. Это выводит «значение», поскольку 1 преобразуется в «1». См. Средства доступа к свойствам

Поэтому, когда вы вызываете obj[arg] , вы на самом деле вызываете что-то вроде obj[arg.toString()] . Вот arg массив аргументов, например [{foo: 'bar'}] . Попробуйте вызвать [{foo: 'bar'}].toString() , и вы получите [object Object] . См. Array.prototype .toString() и Object.prototype .toString() .

Это означает, что для каждого аргумента объекта вы получите один и тот же ключ.

Комментарии:

1. Спасибо, что нашли время объяснить, почему он не работал с объектами в качестве аргументов!

2. Если вы печатаете свой объект кэша при отладке кода, вы, возможно, уже нашли это.