【问题标题】:How to use closure in a recursive function without losing scope in JavaScript?如何在递归函数中使用闭包而不丢失 JavaScript 的范围?
【发布时间】:2015-11-07 15:26:01
【问题描述】:
  • tem.jqw.Callback 对象包含一个可执行函数,一个 CSS 选择器。和循环延迟。
  • tem.jqw.wait 等待 jQuery 被加载,然后遍历 tem.jqw.Callback 对象数组并在找到具有 CSS 的元素后执行它们的函数选择器传入。

我遇到的问题是 tem.jqw.Callback 对象中的 run 函数。第一次调用 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();

【问题讨论】:

  • setTimeout(this.run.bind( this ), 100)

标签: javascript object recursion scope closures


【解决方案1】:

你可以使用 bind 来设置这个

this.run()改成

this.run.bind(this)

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

var self = this;

然后传递 self 以获得更好的可读性

【讨论】:

  • this.run.bind(this) 有效!我在哪里做:var self = this?这会是 run 函数中要做的第一件事吗?然后,我需要做什么:setTimeout(self.run, 100)?谢谢!
  • 我更喜欢描述对象的名称而不是 self,后者并不比 thisthat 更具描述性。也许callback = this.
猜你喜欢
  • 2021-10-25
  • 1970-01-01
  • 2011-01-31
  • 2013-03-18
  • 2016-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多