ES6 Spread operator (Rest Parameter) - syntax fails with Safari 9

1.4k views Asked by At

UPDATE: FelixKling rightly points out that my use of the term spread operator was incorrect and it should be Rest Parameter. Using the compatibility table I linked to, it clearly shows that the Rest Parameter is not supported in Safari 9. Clarifying that it is a Rest Parameter is the real answer to this question (although the example of how to rewrite the function is excellent).


I wrote a javascript function performance tester which tests how long a function takes to run. It uses the ES6 spread operator (...) and it works fine in Firefox but not in Safari (up to version 9.1.2). According to this compatibility chart, Safari 9 received a score of 9/15 for the spread operator and I presume this is a shortcoming of Safari 9. Is there an ES6 way to rewrite it so it will work with Safari 9 (and if not, why the "9" in 9/15 - I would think it means that it must have worked in some situations)?

function timerTest(func, iterations, ...someData) {
   if (typeof iterations == "undefined") {
      iterations = 1;
   }
   var start = performance.now();
   for (var i = 0; i < iterations; i++) {
      func.apply(this, someData);
   }

   var funcName = /function ([^\(]+)/.exec(func.toString())[0];
   v("Time to run " + funcName + " for " + iterations + " time(s): " + (performance.now() - start));
   return performance.now() - start;
}

A sample of how it is used (in this case, determining which of the 3 methods is faster to test if an element has a class assigned):

var e = document.getElementById("test");
timerTest(hasClass, 1000000, e, "x");
timerTest(hasClass2, 1000000, e, "x");
timerTest(hasClass3, 1000000, e, "x");

function hasClass(e, name) {
   if (typeof e !== "undefined" && typeof e.className !== "undefined") {
      return new RegExp('(\\s|^)' + name + '(\\s|$)').test(e.className);
   }
   return false;
}

function hasClass2(e, name) {
   if (typeof e !== "undefined" && typeof e.className !== "undefined") {
      return (' ' + e.className + ' ').indexOf(' ' + name + ' ') > -1;
   }
   return false;
}

function hasClass3(e, name) {
   if (typeof e !== "undefined" && typeof e.classList !== "undefined") {
      return e.classList.contains(name)
   }
   return false;
}
1

There are 1 answers

2
Andrés Andrade On BEST ANSWER

Use arguments object

// call your timerTest function
timerTest(hasClass, 1000000, e, "x");

function timerTest(func, iterations) {

  if (typeof iterations == "undefined"){
     iterations = 1;
  }
  var start = performance.now();
  //Get parameters from arguments
  var args = Array.prototype.slice.call(arguments, 2);

  for (var i = 0; i < iterations; i++){
    func.apply(this, args);
  }

  var funcName = /function ([^\(]+)/.exec(func.toString())[0];
  v("Time to run " + funcName + " for " + iterations + " time(s): " + (performance.now() - start));
    return performance.now() - start;
}