2017-02-16 4 views
2

Я пытаюсь оптимизировать использование функции, чтобы проверить, является ли число простым или нет.Кэширование в Javascript без использования глобальной переменной

я написал следующую функцию:

function isPrime(num) { 
    var start = 2; 

    // code to check whether num has already been checked for Prime 

    while(start <= Math.sqrt(num)) { 
     if (num % start++ < 1) { 
     return false; 
     } 
    } 
    return num > 1; 
} 

Однако перед выполнением моего while цикла я хочу, чтобы проверить, является ли число уже было передано через мою функцию IsPrime, так что я могу вернуться ли это является простым или не без выполнения цикла while.

Примечание. Я хочу сделать это без использования глобальной переменной или без расширения Object.prototype.

+0

Обратите внимание, что если вы заботитесь о производительности, вы также должны смотреть в с помощью вместо этого, или * по крайней мере * принять вызов 'Math.sqrt()' из заголовка цикла. В любом случае, это будет эффективно служить целям вашего кеша. – Pointy

+0

Как будет служить в качестве моего кеша? – nashcheez

+0

Поскольку seive * - * карта каждого числа (до предела того, сколько было вычислено) и флаг, указывающий, является ли число простым. – Pointy

ответ

3

Вы можете использовать технику Memoization.

Memoization - это метод программирования, который пытается повысить производительность функции путем кэширования ранее вычисленных результатов.

Основная идея заключается в том, что мы строим пустой объект, а затем добавляем Keys как значение хеша или значение аргумента, а затем, если мы получим аргумент, который уже доступен в ключах Object, мы возвращаем значение Object для этого объекта ключ.

Существует несколько вариантов функции ниже, но эта функция работает намного лучше, чем другая реализация. Фрагмент кода, взятый из Адди Османи, статья here.

function memoize(fn) { 
     return function() { 
      var args = Array.prototype.slice.call(arguments), 
       hash = "", 
       i = args.length; 
      currentArg = null; 
      while (i--) { 
       currentArg = args[i]; 
       hash += (currentArg === Object(currentArg)) ? 
       JSON.stringify(currentArg) : currentArg; 
       fn.memoize || (fn.memoize = {}); 
      } 
      return (hash in fn.memoize) ? fn.memoize[hash] : 
      fn.memoize[hash] = fn.apply(this, args); 
     }; 
    } 

Использование:

var cachedIsPrime = memoize(isPrime); 
var isPrime = cachedIsPrime(2); 
isPrime = cachedIsPrime(3); 

И тогда вы можете передать функцию, которая должна быть Memoized.

OP Примечания: Для приведенного выше контекста с одним аргументом, простая функция memoize как следующий делает работу:

var memoize = function(passedFunc) { 
    var cache = {}; 
    return function(x) { 
     if (x in cache) return cache[x]; 
     return cache[x] = passedFunc(x); 
    }; 
}; 
1

Что вы ищете, это memoization pattern.

От Wikipedia:

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

Вы можете написать your own memoize function (как это было предложено другими ответами), или вы можете использовать один из многих оптимизированы и хорошо проверенных реализации имеющейся на НОМ, как fast-memoize.js или memoizee. Если вы уже используете Lodash, у него также есть функция _.memoize.

Пример:

var isPrime = memoize(/* your function */) 

isPrime(2) // => true 
isPrime(2) // => true (from the cache) 
3

Объявляет переменную внутри IIFE, чтобы создать closure.

var isPrime = (function() { 
    var checked_numbers = []; 

    function isPrime(num) { ... } 

    return isPrime; 
}(); 

checked_numbers находится в области для возвращаемой isPrime функции (которая доступна за пределами IIFE, поскольку она (сама функция) присваивается глобальной переменной) , но ничего вне IIFE не может прикоснуться к нему.