【问题标题】:Javascript recursive call creates range-errorJavascript递归调用创建范围错误
【发布时间】:2017-11-13 22:32:48
【问题描述】:

我正在尝试使以下脚本正常工作,但是当它进入 continueAnimation 函数时,它不会更新 cPreloaderTimeout 变量,而是在“未捕获 RangeError:超出最大调用堆栈大小”中运行。

    var loadingIcon = {

    cSpeed : 8,
    cWidth : 64,
    cHeight : 32,
    cTotalFrames : 7,
    cFrameWidth : 64,
    cImageSrc : 'sprites.png',

    cImageTimeout : false,
    cIndex : 0,
    cXpos : 0,
    cPreloaderTimeout : false,
    SECONDS_BETWEEN_FRAMES : 0,

    startAnimation : function() {
        document.getElementById('loaderImage').style.backgroundImage='url('+ this.cImageSrc+')';
        document.getElementById('loaderImage').style.width=this.cWidth+'px';
        document.getElementById('loaderImage').style.height=this.cHeight+'px';

        //FPS = Math.round(100/(maxSpeed+2-speed));
        FPS = Math.round(100/this.cSpeed);
        SECONDS_BETWEEN_FRAMES = 1 / FPS;

        this.cPreloaderTimeout = setTimeout( this.continueAnimation(), SECONDS_BETWEEN_FRAMES/1000);

    },

    continueAnimation : function() {
        this.cXpos += this.cFrameWidth;
        //increase the index so we know which frame of our animation we are currently on
        this.cIndex += 1;

        //if our cIndex is higher than our total number of frames, we're at the end and should restart
        if (this.cIndex >= this.cTotalFrames) {
            this.cXpos =0;
            this.cIndex=0;
        }

        if(document.getElementById('loaderImage'))
            document.getElementById('loaderImage').style.backgroundPosition=(-this.cXpos)+'px 0';


        this.cPreloaderTimeout = setTimeout(this.continueAnimation(), SECONDS_BETWEEN_FRAMES*1000);
    },

    stopAnimation : function(){//stops animation
        clearTimeout( this.cPreloaderTimeout );
        this.cPreloaderTimeout = false;
    }

}

jQuery( document ).ready(function() {

    jQuery( document ).on("click", "#test", function(){

        var loader = loadingIcon;

        loader.startAnimation();

        setTimeout( loader.stopAnimation(), 3000);

    });
});

起初它是一个普通的 javascript 脚本,但我试图从中创建一个对象,以便它可以重复使用并同时多次使用。现在的问题是触发 startAnimation 或 continueAnimation 时 cPreloaderTimeout 变量设置不正确。

【问题讨论】:

  • 因为你没有正确使用setTimeout。从setTimeout(this.continueAnimation(), ...) 中删除() 并阅读有关setTimeout 的更多信息。
  • 注意:当您修复setTimeout 问题时,您将陷入this issue

标签: javascript object methods stack-overflow


【解决方案1】:

您有几个问题。

首先,您的 cPreloaderTimeout 不会像您想象的那样设置,因为您没有创建具有原型的对象,因此该函数内 this 的范围将是函数本身,不是对象。

其次,setTimeout 接受一个函数,但你在尝试使用它时调用了该函数,因此发送给 setTimeout 的值将是函数的结果,而不是函数本身。

请考虑以下格式:

function LoadIcon() {
  this.cSpeed = 8;
  // All your other properties
}

LoadIcon.prototype.startAnimation = function() { 
  // your startAnimation function, concluding with
  this.preloaderTimeout = setTimeout(this.continueAnimation.bind(this), SECONDS_BETWEEN_FRAMES/1000); 
}

// the rest of the methods built the same way

//then, your calling code would look like:

var loadIcon = new LoadIcon();
loadIcon.startAnimation();

编辑 我更新了setTimeout 调用,因为我忘记了绑定到this 以在回调触发时正确确定范围。

【讨论】:

  • 我已经尝试过这种格式,但是在 continueAnimation 中我不能使用“this”,因为它的窗口不是 LoadIcon,而是它的窗口
  • @MartijnBastiaansen 对,对不起。这个问题现在已经解决了,再看看吧。
猜你喜欢
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
  • 2021-12-25
  • 2012-01-02
  • 2017-10-30
  • 2014-05-31
  • 1970-01-01
  • 2011-09-13
相关资源
最近更新 更多