Phi Quang Phuoc
Phi Quang Phuoc

Reputation: 243

Invoke a function with is faster than directly invoking?

I tested performance with a script from "Secrets of Javascript Ninja":

function isPrime(number) {
  if (number < 2) {
    return false;
  }
  for (let i = 2; i < number; i++) {
    if (number % i === 0) {
      return false;
    }
  }
  return true;
}

console.time("isPrime");
isPrime(1299827);
console.timeEnd("isPrime");

console.time("isPrime");
isPrime.apply(1299827);
console.timeEnd("isPrime");

And the result is:

isPrime: 8.276ms
isPrime: 0.779ms

Seems that "apply" is faster?

Upvotes: 2

Views: 57

Answers (3)

seunggabi
seunggabi

Reputation: 1822

You have to read this.

reference: https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

This point is Array.prototype.apply(context = this, args = []), so your code is wrong.

Change your code to this.

// incorrect.
isPrime.apply(1299827);
// correct.
isPrime.apply(this, 1299827);

Upvotes: 2

CertainPerformance
CertainPerformance

Reputation: 370819

Your comparison is not accurate, because the first parameter passed to apply is the this value of the called function, and the second parameter passed to apply is an array of parameters that function is to be called with. So, your apply is not calling isPrime with any parameters, so no iterations run, because the condition i < number is not fulfilled when i is 2 and number is undefined:

function isPrime(number) {
  console.log('calling with ' + number);
  if (number < 2) {
    return false;
  }
  for (let i = 2; i < number; i++) {
    if (number % i === 0) {
      return false;
    }
  }
  return true;
}

console.time("isPrime");
isPrime(1299827);
console.timeEnd("isPrime");

console.time("isPrime");
isPrime.apply(1299827);
console.timeEnd("isPrime");

If you use apply properly and pass in undefined, [1299827], the result is as expected, very similar. You should also use performance.now() for better precision than console at the millisecond level, though for such a quick operation you might not see that might difference anyway:

function isPrime(number){
    console.log('calling with ' + number);
    if(number < 2) { return false; }
    for(let i = 2; i < number; i++) {
        if(number % i === 0) { return false; }
    }
    return true;
}

const t1 = performance.now();
isPrime(1299827);
const t2 = performance.now();

isPrime.apply(undefined, [1299827]);
console.timeEnd("isPrime");
const t3 = performance.now();
console.log(t2 - t1);
console.log(t3 - t2);

Upvotes: 5

Chris Li
Chris Li

Reputation: 2671

The syntax for .apply is

function.apply(thisArg, [argsArray])

the first parameter thisArg refers to the value of 'this' when calling the function, in your case isPrime.apply(1299827) you passed in 1299827 as 'this' but no parameter, so it's really isPrime(), the for loop is not excuted so it's faster
more on .apply here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

Upvotes: 2

Related Questions