Sieve of Eratosthenes using a Javascript array
Since you're just doing steps of 1 and starting with 0, we don't need to take account for those. Your range function can be simplified into the following. 

function range(length){
  return Array.apply(null, Array(length)).map(function (_, i) {return i;});
}


Also, a comparison is already a boolean by itself. So your isNotNull could be simplified into the following. We could coerce value into a boolean by using !!, since we're working with numbers, we might encounter 0 which is falsy but technically not null. So we compare explicitly with null instead to avoid this.

function isNotNull(value) {
    return value !== null;
}


You could also inline your search for the next prime into your primes function. You can simply check your number list if the next number has been nulled, and if so, have the loop in primes skip the number.

With that (and hopefully my understanding of the algorithm isn't wrong), here's my take:



function range(length) {
  return Array.apply(null, Array(length)).map(function(_, i) { return i; });
}

function getPrimes(end) {

  // We get the numbers below the square root of the limit. The | 0 is 
  // dropping the decimal info, and since range here is zero-indexed,
  // we add 1.
  return range((Math.sqrt(end) | 0) + 1).reduce(function(numbers, root, index) {

    // If the number at root is null, then its multiples may have been
    // nulled by an earlier prime. We bail out. Nothing to do here.
    if (numbers[root] === null) return numbers;

    // We null every multiple, provided it's not 0 and 1
    else if (root !== 0 &amp;&amp; root !== 1)
      for (var i = root * root; i &lt; numbers.length; i += root)
        numbers[i] = null;

    // If we reached here, then probably you're looking at 0 or 1
    else numbers[root] = null;

    return numbers;

    // Here's the array that generates 0-to-end. Again, range is
    // zero-indexed so the + 1 is necessary.
  }, range(end + 1)).filter(function(i) {

    // Since 0 and 1 are already nulled, they will fall off here. No
    // additional slicing needed.
    return i !== null;
  });
}

document.write(getPrimes(121).join(','));