如何将未指定数量的参数传递给setInterval

时间:2016-04-14 11:08:34

标签: javascript setinterval

我需要创建一个间隔包装器来跟踪它是否已被清除。

传递给区间回调的参数数量应该是可变的。所以这是我为测试它而实现的代码(不工作):



function MyInterval() {
  var id = setInterval.apply(this, arguments); // NOT VALID!!
  this.cleared = false;
  this.clear = function() {
    this.cleared = true;
    clearInterval(id);
  };
}

var x = 2;
var y = 3;
var fn = function() {
  x = x + y;
  console.log(x);
};
var interval = new MyInterval(fn, 5000, x, y);




3 个答案:

答案 0 :(得分:1)

在对setInterval的调用中,this必须引用全局对象,因此在构造函数中需要this而不是window

var id = setInterval.apply(window, arguments);
// here -------------------^

(或者在宽松模式下,您可以使用undefinednull。)

然后它起作用,至少在setInterval是一个真正的JavaScript函数的浏览器上,因此有apply

function MyInterval() {
  var id = setInterval.apply(window, arguments);
  this.cleared = false;
  this.clear = function() {
    this.cleared = true;
    clearInterval(id);
  };
}

var x = 2;
var y = 3;
var fn = function() {
  x = x + y;
  log(x);
};
var interval = new MyInterval(fn, 500, x, y);
setTimeout(function() {
  interval.clear();
}, 3000);

function log(msg) {
  var p = document.createElement('p');
  p.appendChild(document.createTextNode(msg));
  document.body.appendChild(p);
}

注意但是,主机提供的功能只需要是可调用的,它们 不需要从Function.prototype继承,所以它们是不需要/保证apply。现代浏览器确保它们可以,但早期的浏览器(例如IE8)没有。我无法谈论applysetInterval的支持程度如何。

如果您需要支持可能没有它的浏览器,只需使用您自己的功能:

function MyInterval(handler, interval) {
  var args = Array.prototype.slice.call(arguments, 2);
  var tick = function() {
    handler.apply(undefined, args);
  };
  var id = setInterval(tick, interval);
  this.cleared = false;
  this.clear = function() {
    this.cleared = true;
    clearInterval(id);
  };
}

这也有一个优点,即它在setInterval(相当旧的)上不支持其他args的浏览器上也能正常工作。

示例:

function MyInterval(handler, interval) {
  var args = Array.prototype.slice.call(arguments, 2);
  var tick = function() {
    handler.apply(undefined, args);
  };
  var id = setInterval(tick, interval);
  this.cleared = false;
  this.clear = function() {
    this.cleared = true;
    clearInterval(id);
  };
}

var x = 2;
var y = 3;
var fn = function() {
  x = x + y;
  log(x);
};
var interval = new MyInterval(fn, 500, x, y);
setTimeout(function() {
  interval.clear();
}, 3000);

function log(msg) {
  var p = document.createElement('p');
  p.appendChild(document.createTextNode(msg));
  document.body.appendChild(p);
}

您可能想要使用新的ES2015传播运营商:

var id = setInterval(...arguments);

...但请注意,如果你进行了细分(现在你必须这样做),它最终会被apply调用,因此你会遇到是否支持apply的问题

答案 1 :(得分:1)

我建议您通过"选项"超时参数。



var MyInterval = (function(window) {
  return function(callbackFn, timeout, options) {
    var id = setInterval.apply(window, arguments);
    this.cleared = false;
    this.clear = function() {
      this.cleared = true;
      clearInterval(id);
    };
  }
}(window));

var fn = function(opts) {
  opts.x += opts.y;
  console.log('x = ', opts.x);
};
var opts = {
  x: 2,
  y: 3
};
var ms = 5000;

var interval = new MyInterval(fn, ms, opts);

// Bootstrap a custom logger. :)
console.log = function() {
  var logger = document.getElementById('logger');
  var el = document.createElement('LI');
  el.innerHTML = [].join.call(arguments, ' ');
  logger.appendChild(el);
  logger.scrollTop = logger.scrollHeight;
}

body{background:#7F7F7F;}h1{background:#D7D7D7;margin-bottom:0;padding:0.15em;border-bottom:thin solid #AAA;color:#444}#logger{height:120px;margin-top:0;margin-left:0;padding-left:0;overflow:scroll;max-width:100%!important;overflow-x:hidden!important;font-family:monospace;background:#CCC}#logger li{list-style:none;counter-increment:step-counter;padding:.1em;border-bottom:thin solid #E7E7E7;background:#FFF}#logger li:nth-child(odd){background:#F7F7F7}#logger li::before{content:counter(step-counter);display:inline-block;width:1.4em;margin-right:.5em;padding:.25em .75em;font-size:1em;text-align:right;background-color:#E7E7E7;color:#6A6A6A;font-weight:700}

<h1>Custom HTML Logger</h1><ol id="logger"></ol>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

我创建了一个实用程序函数而不是构造函数来解决您的问题。

class produit_produit(osv.osv):
    """le produit"""
    _name = 'produit.produit'
    _columns = {
        'product_id': fields.char('product_id',size=30,required=True, help='product_id'),
        'product_libelle': fields.char('product_libelle',size=60,required=True, help='product_libelle'),
        'type': fields.char('type',required=True, help='type'),
        'prix': fields.many2one('produitachete.produitachete',help='prix'),
    }
produit_produit()

class produitachete_produitachete(osv.osv):
   """produit achete"""
   _name = 'produitachete.produitachete'
   _columns = {
       'prix_achat': fields.char('prix_achat',size=30,required=True, help='prix_achat'),

   }
produitachete_produitachete()

希望这有帮助。