【问题标题】:ES6 Spread operator (Rest Parameter) - syntax fails with Safari 9ES6 Spread 运算符(Rest Parameter) - Safari 9 语法失败
【发布时间】:2017-05-17 02:14:23
【问题描述】:

更新:FelixKling 正确地指出我对术语 spread operator 的使用是不正确的,它应该是 Rest Parameter。使用我链接到的兼容性表,它清楚地表明 Safari 9 不支持 Rest Parameter。澄清它是 Rest Parameter 是这个问题的真正答案(尽管如何重写函数的示例非常好)。


我编写了一个 javascript 函数性能测试器,用于测试函数运行所需的时间。它使用 ES6 扩展运算符 (...),它在 Firefox 中运行良好,但在 Safari 中无法正常运行(直到版本 9.1.2)。根据compatibility chart,Safari 9 的扩展运算符得分为 9/15,我认为这是 Safari 9 的一个缺点。是否有 ES6 方法来重写它,以便它可以与 Safari 9 一起使用(如果没有,为什么 9/15 中的“9” - 我认为这意味着它必须在某些情况下有效)?

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;
}

如何使用它的示例(在这种情况下,确定 3 种方法中的哪一种更快地测试元素是否已分配类):

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;
}

【问题讨论】:

  • 点击 9/15 展开。 “带字符串,在函数调用中”是否
  • 这可以像将timerTest(func, iterations, ...someData) 替换为function timerTest(func, iterations) { var someData = Array.prototype.slice.call(arguments, 2); ...} 一样简单。
  • @jeffcarey - 啊,当我点击 9/15 时,我没有注意到它展开了。感谢您指出此功能。这让我知道我有哪些选择。
  • @robG - 感谢您提醒我有关 arguments 关键字的信息。这是一个伟大而简单的解决方案。
  • ... is not an operator 在您的情况下,它与“传播”无关。

标签: javascript safari ecmascript-6 spread-syntax


【解决方案1】:

使用arguments 对象

// 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;
}

【讨论】:

  • 该函数适用于您的更改,但是当我比较运行示例中显示的函数所需的时间时,您的方法运行时间要长 67% 到 10 倍。解决方案是使用var args = Array.prototype.slice.call(arguments, 2); 将参数放入一个数组,然后将argsfunc.apply(this, args); 一起传递
  • @mseifert 对,如果您要测量时间,在循环内创建数组根本不是一个好主意,我想我在调用函数之前放置代码只是为了便于阅读。我刚刚编辑了我的答案。
猜你喜欢
  • 2017-08-28
  • 2020-02-11
  • 2017-03-26
  • 1970-01-01
  • 2018-01-22
  • 2017-04-15
  • 1970-01-01
  • 1970-01-01
  • 2021-09-22
相关资源
最近更新 更多