首页 > js对象的方法中引用自身对象,无法找到对象?

js对象的方法中引用自身对象,无法找到对象?

一个“秒表”对象,我将他放入jquery的$(function(){})中,整个JS文件代码如下:

$(function () {
    var StopWatch =
    {
        stopWatchTimeSet:null,
        startTime: 0,
        stopTime: 0,
        elapsed: 0,
        ss: 0,
        s: 0,
        started: false,
        interval: 10,
        start: function () {
            that=this; //此行稍后用来dubug
            if ((this.ss % 100) == 0 && (this.ss > 0)) {
                this.s += 1;
                this.ss = 0;
            }
            var s = this.checkTime(this.s);
            var ss = this.checkTime(this.ss);
            this.ss += 1;
            $('.stopWatch').text(s + ':' + ss);
            this.stopWatchTimeSet = setTimeout('StopWatch.start()', 10);
        },
        pause: function () {
            this.started = false;
            clearTimeout(this.stopWatchTimeSet);
        },
        stop: function () {
            this.started = false;
            clearTimeout(this.stopWatchTimeSet);
            this.s = 0;
            this.ss = 0;
            $('.stopWatch').text('00:00');
        },
        checkTime: function (i) {
            if (i < 10) {
                i = '0' + i;
            }
            return i;
        }
    };
    
    $某DOM对象.click(function(){
    StopWatch.start();
    });
 })

问题来了:
点击此DOM对象后,代码错误提示我在setTimeout('StopWatch.start()', 10);这句代码里没有找到StopWatch对象。
尝试一下两种方法可以解决问题:
1.将setTimeout('StopWatch.start()', 10);中的StopWatch替换成that
2.将StopWatch前面的var去掉或者将var StopWatch={....}移动到$(function(){})外面也就是全局作用域中(我想这个应该是等价)。

疑惑:为什么会出现找不到对象的提示?我已经在dom对象click事件里引用了StopWatch,照理已经闭包,StopWatch不会被GC,于是我又做了以下实验:

$某DOM对象.click(function(){
        alert(StopWatch);  //[object object],证明StopWatch至少在这里仍然存在
        StopWatch.start();
        });
        

那么到底什么原因造成我的setTimeout('StopWatch.start()', 10);中找不到StopWatch对象?

更新:抱歉我that前面忘了加var,加上之后果然也提示找不到变量,所以上文第一种解决方法其实跟第二种一样。。


setTimeout('StopWatch.start()', 10);
传递字符串给setTimeout函数时,JS引擎会把字符串使用Function构造函数将其转换为函数对象,
使用new Function创建的函数没有闭包作用域的~~
StopWatch会直接在全局作用域下找

setTimeout(new Function('StopWatch.start();'), 10);

Functions created with the Function constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function constructor was called. This is different from using eval with code for a function expression.

通过下面的代码可以更清楚写:
全部输出global

(function(){
    var foo={
        name:'foo',
        testFun:function(){
            console.log(this.name);
        }
    }
    
    setTimeout('foo.testFun();', 10);
}());

var foo={
    name:'global',
    testFun:function(){
        console.log(this.name);
    }
}

setTimeout('foo.testFun();', 10);

针对你的问题的解决方法,供参考:
1.

    var __that__=this;
    if(!this.started){
        this.stopWatchTimeSet = setTimeout(function(){
            __that__.start()
        }, 10);
    }

2.

    if(!this.started){
        this.stopWatchTimeSet = setTimeout(this.start.bind(this), 10);
    }
【热门文章】
【热门文章】