为什么无法在JavaScript中运行“Class”调用本身?

时间:2013-04-14 03:22:32

标签: javascript

我无法弄清楚这段代码有什么问题。 Firefox的错误控制台告诉我:“ this.animateImgSlider不是函数”。

我希望用this.selectImage()拨打jsItems[0].selectImage(0),然后在this.animateImgSlider()为假之前调用selfCall几次:

function WindowItem(inId) {
    this.id = inId;
    this.imgSliderTarget = 0;
    this.imgSlider = document.getElementById("imgSlider"+inId);

    this.animateImgSlider = function() {
        var selfCall = true;
        var currLeft = parseInt(this.imgSlider.style.left, 10);
        if (currLeft < this.imgSliderTarget) {
            currLeft += 8;
            if (currLeft >= this.imgSliderTarget) {
                currLeft = this.imgSliderTarget;
                selfCall = false;
            }
        }
        else {
            currLeft -= 8;
            if (currLeft <= this.imgSliderTarget) {
                currLeft = this.imgSliderTarget;
                selfCall = false;
            }
        }
        this.imgSlider.style.left = currLeft+"px";
        if (selfCall) setTimeout("this.animateImgSlider()", 0);
    }

    this.selectImage = function(inImg) {
        this.imgSliderTarget = -inImg*488;
        this.animateImgSlider();
    }
}
var jsItems = new Array();
jsItems.push(new WindowItem(0));

此行是抛出错误的行:

if (selfCall) setTimeout("this.animateImgSlider()", 0);

2 个答案:

答案 0 :(得分:5)

请改用:

if (selfCall) {
    var self = this;
    setTimeout(function () {
        self.animateImgSlider();
    }, 0);
}

(当然,我最有意义的是在顶部声明self并在整个函数中使用它而不是this

传递给setTimeout以执行的字符串在全局范围内完成,这意味着this指的是window。它不会在setTimeout调用的当前范围内执行。

在旁注中,作为建议,我会将您的animateImgSliderselectImage方法移到外部,并转移到WindowItem原型中,以便所有实例共享它们,而不是每次都创建一个新的匿名函数。例如,你有:

function WindowItem(inId) {
    // blah blah
}

WindowItem.prototype.animateImgSlider = function () {
    // blah blah
};

WindowItem.prototype.selectImage = function(inImg) {
    // blah blah
};

this的值仍将引用特定实例,除非您尝试在setTimeout参数的字符串中使用它:)

这显然不是必需的,因为您的代码目前工作正常,但它是在构造函数上声明方法以供共享实例的常用约定。

答案 1 :(得分:2)

您可以使用bind。这是link

if (selfCall) {
    setTimeout(function () {
        this.animateImgSlider();
    }.bind(this), 0);
}