Find and print all prime numbers (less than 10000)
This is a very nice start! It is clear that you have put some effort into making your code clear and easy to read - it paid off. That said, there are a few things I would recommend changing. 


Don't take input as a float. This opens up the possibility for confusion without providing any benefit to the user.
Include USER_INPUT in the range tested for primes. If I input 5 using the form I only get 2 and 3, while I expected 2, 3, and 5. 
Why do you cache PRIMES only to reset it every time findPrimes is called? If you are going to spend the memory to save a list of primes, you might as well make use of it.
I see you have started to optimize your solution by only going up to Math.sqrt(n), but you are still using an inefficient algorithm. I would encourage you to look into the Sieve of Eratosthenes as your input is bounded.
Don't mix your logic and display code. While for a small project like this it isn't much of an issue, if you want to use PrimeFinder somewhere else in your application you would have to rewrite it to strip out all of the page specific code.




With this in mind, here is how I would write PrimeFinder as a module without handling DOM manipulations. 



const PrimeFinder = (function() {
    let PRIMES = [];
    const MAX_RANGE = 10000;

    function _generatePrimes() {
        // Computing 10000 is not much different than computing 500, so fill the entire array.
        let marks = Array(MAX_RANGE + 1).fill(false)
        for (let i = 2; i &lt;= MAX_RANGE; i++) {
            // Already marked as non-prime?
            if (marks[i]) continue;
            // Mark all multiples
            for (let j = i * 2; j &lt;= MAX_RANGE; j += i) {
                marks[j] = true;
            }
            // This number hasn't been marked, and therefore is prime
            PRIMES.push(i);
        }
    }

    function isPrime(n) {
        if (Number.isNaN(n)) throw Error('n must be a number');
        if (n &gt; MAX_RANGE || n &lt; 0) throw Error('n is out of range.');
        if (!PRIMES.length) _generatePrimes();
        // Could be sped up with a binary search.
        return PRIMES.includes(n);
    }

    function findPrimes(upperBound) {
        if (Number.isNaN(upperBound)) throw Error('upperBound must be a number');
        if (upperBound &gt; MAX_RANGE) throw Error(`upperBound must be less than ${MAX_RANGE}`);
        if (upperBound &lt; 0) throw Error('upperBound must be at least 0');

        if (!PRIMES.length) _generatePrimes();

        let index = PRIMES.findIndex(n =&gt; n &gt; upperBound);
        // Return a copy of the array so users can't mess with the module
        return index == -1 ? [...PRIMES] : PRIMES.slice(0, index);
    }

    return { isPrime, findPrimes };
}());

function displayArray(parent, items) {
  parent.innerHTML = '';
  items.forEach(value =&gt; {
    let el = document.createElement('li');
    el.textContent = value;
    parent.appendChild(el);
  });
}

document.querySelector('input').addEventListener('input', event =&gt; {
  let num = parseInt(event.target.value, 10);
  if (num &gt; 10000) event.target.value = num = 10000;
  if (num &lt; 0 || Number.isNaN(num)) event.target.value = num = 0;
  displayArray(
    document.querySelector('ul'),
    PrimeFinder.findPrimes(num)
  );
});
&lt;input type="number" /&gt;
&lt;ul&gt;&lt;/ul&gt;






The snippet behaves similarly to the provided snippet without mixing DOM logic into the PrimeFinder functionality - this makes it possible to easily pull out PrimeFinder for use in other projects (even those where the DOM might not exist).