如何在递归函数中使用闭包而不会丢失JavaScript中的范围?

时间:2015-08-14 11:26:02

标签: javascript object recursion scope closures

  • tem.jqw.Callback 对象包含一个可执行函数,一个CSS选择器。和循环延迟。
  • tem.jqw.wait 等待加载jQuery,然后遍历 tem.jqw.Callback 对象数组,并在找到元素后执行其功能传入CSS选择器。

我遇到的问题是 tem.jqw.Callback 对象中的运行功能。当第一次调用run函数时,如果元素存在,一切都很好,可执行函数运行正常。但是,如果该元素尚不存在,并且我们需要循环,则该函数在 setTimeout(this.run,100)执行一次后失去作用域。例如,当run函数第二次执行时,this.selector或this.fn变为未定义。如何在不使用全局变量的情况下解决这个问题?提前谢谢。

if (typeof tem !== "object") {
  tem = {};
}

tem.jqw = {};
tem.jqw.retries = 0;
tem.jqw.maxRetries = 100;
tem.jqw.delay = 100;
tem.jqw.callbacks = [];

tem.jqw.Callback = function (fn, selector, delay) {
  this.fn = fn;
  this.selector = (typeof selector === "string" && selector.length > 0) ? selector : document;
  this.delay = (typeof delay === "number" && delay > 0 && delay < 1000) ? delay : 100;

  this.retries = 0;
  this.maxRetries = 100;

  this.start = function () {
    this.run();
  };

  this.run = function () {
    if (jQuery(this.selector).length > 0) {
      console.log("[OPDEBUG] tem.jqw.Callback.run says: " + this.selector.toString() + " is ready. Executing callback function...");
      this.fn();
    } else {
      this.retries++;
      console.log("[OPDEBUG] tem.jqw.Callback.run says: typeof this.selector " + typeof this.selector);
      console.log("[OPDEBUG] tem.jqw.Callback.run says: Waiting for " + this.selector.toString() + "...");
      if (this.retries < this.maxRetries) {
        setTimeout(this.run, 100);
      }
    }
  };
};

tem.jqw.wait = function () {
  if (typeof jQuery === "function") {
    console.log("[OPDEBUG] tem.jqw.wait says: jQuery is ready.");
    for (var i = 0; i < tem.jqw.callbacks.length; i++) {
      if (typeof tem.jqw.callbacks[i] === "object" && typeof tem.jqw.callbacks[i].start === "function") {
        console.log("[OPDEBUG] tem.jqw.wait says: Executing callback function " + (i + 1) + "...");
        tem.jqw.callbacks[i].start();
      }
    }
  } else {
    tem.jqw.retries++;
    console.log("[OPDEBUG] tem.jqw.wait says: " + "Waiting for jQuery " + tem.jqw.retries + "...");
    if (tem.jqw.retries < tem.jqw.maxRetries) {
      setTimeout(tem.jqw.wait, tem.jqw.delay);
    }
  }
};

tem.jqw.callbacks.push(new tem.jqw.Callback(function () {
  jQuery('.hero-inner:first a').css('background-image', 'url("https://www.thedogs.co.nz/Files/PhotoFinishImages/11298_89160.jpg")')
}, ".hero-inner:first"));
tem.jqw.callbacks.push(new tem.jqw.Callback(function () {
  jQuery('.RR-placeholder ul li:first').hide();
}, ".RR-placeholder ul li:first"));
tem.jqw.wait();

1 个答案:

答案 0 :(得分:1)

您可以使用bind来设置此

this.run()更改为

this.run.bind(this)

最好将 this 分配给另一个变量,例如

var self = this;

然后绕过自我以获得更好的可读性