【问题标题】:JavaScript Recursive Callback Function - ReferenceError: function is not definedJavaScript 递归回调函数 - ReferenceError:函数未定义
【发布时间】:2013-11-20 16:00:10
【问题描述】:

我的想法是显示数组中的所有图像。起初,Noise 图像被隐藏,之后它调用 showArray() 函数来显示 Array 中的图像。

Trial = (function() {
  function Trial(imageArray) {
    this._images = new Array();
    this._images = imageArray;
  }

  Trial.prototype.startTrial = function() {
    return $("#noise").hide(0, showImages());
  };

  Trial.prototype.showImages = function() {
    var imageToShow;
    imageToShow = this._images.pop();
    if (imageToShow === void 0) {
      $("#noise").show;
      return;
    }
    $("#img").attr("src", imageToShow.src);
    return $("#img").fadeIn(0).delay(imageToShow.delay).fadeOut(0, showImages());
  };

  return Trial;

})();

image1 = new AMPImage("someImage1.png", 500);  //imagePath, delay in ms
image2 = new AMPImage("someImage2.png", 750);
image3 = new AMPImage("someImage3.png", 1000);

myImageArray = [image1, image2, image3];
trial1 = new Trial(myImageArray);
trial1.startTrial();

但在执行 startTrial() 时我收到错误消息

ReferenceError: showArray 未定义

【问题讨论】:

  • 嗯? showArray 函数在哪里?定义了吗?
  • 哦,在测试了不同的东西后,这是一个错字。我更正了。

标签: javascript recursion callback jquery-callback


【解决方案1】:

根据您的最新编辑:

上下文并不像那样工作。即showImages 不是变量。这是Trial 类原型上的一个方法。如果你想从外部代码调用它,你可以这样做:

myTrial.showImages();

如果您想从Trial 类中的另一个方法调用它,您必须将它作为当前实例上的方法调用。您可以通过this 获得对当前实例的引用。即

this.showImages();

而不是

showImages();

您实际上想要做的不是立即调用该函数,而是希望在动画完成后调用该函数。为此,您将函数作为值传递给动画方法。只需省略 () 即可传递函数。

问题在于 this 上下文是一个善变的野兽,如果你这样做是不正确的。要维护正确的 this 上下文,您必须绑定它:

var showImagesToCallLater = this.showImages.bind(this);

// some time later, perhaps inside another method you can then do:

showImagesToCallLater();

// and this will have the correct `this` context.

所以对于我们的示例,我们需要 .hide(0, this.showImages.bind(this));.fadeOut(0, this.showImages.bind(this));

额外的代码审查

我查看了您的其余代码,提出了您可能希望进行的其他更改。如果您只想让代码尽快运行,您可以忽略这一点:

// There's no need to create an extra closure here,
// we can remove a level of nesting.
function Trial(imageArray) {
  // There's no point writing to `this._images` then immediately
  // overwriting, so we only write to it once here
  this._images = imageArray;
}

Trial.prototype.startTrial = function() {
  // I assume you want to begin showing images once #noise is hidden.
  // To do this, pass a function to hide.
  return $("#noise").hide(0, this.showImages.bind(this));
};

Trial.prototype.showImages = function () {
  var imageToShow;
  imageToShow = this._images.pop();
  if (imageToShow === void 0) {
    // You need to actually call this function
    $("#noise").show();
    return;
  }
  $("#img").attr("src", imageToShow.src);
  // Once one image has been shown, I'm guessing you want to show the next.
  // to do this, we `.bind` the function so it has the correct `this` value.
  return $("#img").fadeIn(0).delay(imageToShow.delay)
                  .fadeOut(0, this.showImages.bind(this));
};

image1 = new AMPImage("someImage1.png", 500);  //imagePath, delay in ms
image2 = new AMPImage("someImage2.png", 750);
image3 = new AMPImage("someImage3.png", 1000);

myImageArray = [image1, image2, image3];
trial1 = new Trial(myImageArray);
trial1.startTrial();

您希望它在动画完成时执行,而不是调用函数,这将使它立即执行。为此,您需要传递实际函数,因此在函数上调用.bind(this)。这样它将在正确的上下文中执行。

您也可以构建一个更“实用”的版本:

function startTrial(imageArray) {
  // note how we pass the function showImage, we don't call it
  $("#noise").hide(0, showImage);
  function showImage() {
    var imageToShow = imageArray.pop();
    if (imageToShow === undefined) {
      $("#noise").show();
      return;
    }
    $("#img").attr("src", imageToShow.src);
    return $("#img").fadeIn(0).delay(imageToShow.delay).fadeOut(0, showImage);
  }
}
var image1 = new AMPImage("someImage1.png", 500);  //imagePath, delay in ms
var image2 = new AMPImage("someImage2.png", 750);
var image3 = new AMPImage("someImage3.png", 1000);

var myImageArray = [image1, image2, image3];
startTrial(myImageArray);

你喜欢哪种风格很大程度上取决于个人品味。功能版让您忘记所有奇怪的this 绑定行为。

【讨论】:

  • 随着您的更改递归工作。但是又出现了一个新问题。 stackoverflow.com/questions/20197553/…
  • 你需要更仔细地阅读我的代码,注意我写的是fn.bind(this)而不是fn()。您正在调用该函数,这使其立即执行,您必须将实际函数作为值传递才能将其作为回调调用。
  • 如何将变量imageArray传递给函数调用? fn(imageArray).bind(this); 不起作用。
  • 你可以只做fn.bind(this, imageArray)或者你可以做function () { this.fn(imageArray) }.bind(this)
  • 您可能不需要这样做。如果您在问题中使用基于原型/类的解决方案,您只需在函数中获取this.imageArray,无需将其作为参数传递。
猜你喜欢
  • 1970-01-01
  • 2017-01-21
  • 1970-01-01
  • 2012-09-26
相关资源
最近更新 更多