构造函数中使用setTimeout引发的问题

今天写了段脚本,结果执行出错,脚本内容大致如下:

function Class1()
{
    this.i = 0;
    this.Add = function()
    {
        this.i++;
        setTimeout(this.Add,1000);
    }
}

var o = new Class1();
o.Add();

调试了好久,猜测是this的问题,修改了下代码:

function Class1()
{
    this.i = 0;
    this.Add = function()
    {
        if(this instanceof Class1)alert("Class1");
        if(this == window)alert("window");
        this.i++;
        setTimeout(this.Add,1000);
    }
}

var o = new Class1();
o.Add();

第一次提示"Class1",第二次提示"window",随即脚本出错。为了说明问题,将脚本分解执行:

/*
    第一部分
*/
function Class1()
{
    this.i = 0;
    this.Add = function()
    {
        this.i++;
    }
}

var o = new Class1();
o.Add();

/*
    第二部分
*/
//此处用调用普通函数的方式调用构造函数,构造函数中的this指的是window对象[1]
//this.i++后this.i的值为NaN,因window对象没有Add方法脚本出错
setInterval(function(){this.i++;setTimeout(this.Add,1000);},1000);

正确的脚本:

function Class1()
{
    var _me = this;
    this.i = 0;
    this.Add = function()
    {
        this.i++;
        setTimeout(function(){_me.Add();},1000);
    }
}

var o = new Class1();
o.Add();

相当于:

function Class1()
{
    var _me = this;
    this.i = 0;
    this.Add = function()
    {
        this.i++;
    }
}

var o = new Class1();
setInterval(function(){o.Add();},1000);

2009-07-23 借助闭包实现:

//闭包含数
Function.prototype.bind = function(obj) {
    var method = this;
    return function() {
        return method.apply(obj, arguments);
    };
}

function Class1()
{
    var _me = this;
    this.i = 0;
    this.Add = function()
    {
        this.i++;
        alert(this.i);
        setTimeout(_me.Add.bind(_me),1000);
    }
}

var o = new Class1();
o.Add();

《JavaScript权威指南》第五版P936:

setTimeout(code,delay),当code执行的时候,它是在Window对象的环境中执行的。如果code是一个函数,Window对象就是this关键字的值。如果code是一个字符串,它是在全局作用域中执行的,而Window对象是作用域链上唯一的对象。即便setTimeout()的调用发生在一条长长的作用域链上的一个函数之中,这也是成立的。

参考

[1]. 再说Js构造函数:http://www.mzwu.com/article.asp?id=2145

上一篇: 游泳姿势图解
下一篇: 浮动广告类
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags:
最新日志:
评论: 0 | 引用: 0 | 查看次数: 4260
发表评论
登录后再发表评论!