javascript - js settimeout与this
PHP中文网
PHP中文网 2017-04-10 15:34:25
[JavaScript讨论组]
var Cat = function(name) {
    this.name = name;
}

Cat.prototype.miao = function() {
    console.log("miao miao miao");
    setTimeout(this.miao(), 1000);
}

var cat = new Cat("hahaha");
cat.miao();

上面代码有什么问题吗?
理应1秒调用一次miao()函数,,但是调用次数之多之快却导致了浏览器奔溃

PHP中文网
PHP中文网

认证0级讲师

全部回复(6)
PHP中文网

同意 斑驳光影 说的内容。
另外再补充一下,如果不用bind这个方法,直接写成

javascriptCat.prototype.miao = function() {
    console.log("miao miao miao");
    setTimeout(this.miao, 1000);
}

你会发现程序打出了 两个 miao miao miao 然后就停止了。
在解释这个问题前,我们首先把 setTimeout 方法写成这样:

javascriptsetTimeout(fn,ms);

在第一次调用 setTimeout(this.miao,1000) 中,这个 this,指代的是 Cat 构造函数 new 出来的实例。递归运行后,打印了第二个 miao miao miao后,调用 setTimeout(this.miao,1000) ,此时 this 相当于在上一个 setTimeoutfn 中调用了。因此指代的是全局变量 window, 它并没有 miao 方法,因此会报错。程序也就因此停止了。

简而言之,在 setTimeout(fn,ms) 中,fn 内部的 this指代 window,如果 fn 本身就是 this.method,这个 this就指代所运行时的环境变量。
e.g.

var obj1 = {
    method: function(){
                setTimeout(function(){
                    console.log(this);//window
                },1000);
            }
}         

var obj2 = {
    method: function(){
                setTimeout(this.miao//this 指代obj2
                ,1000);
            },
    miao:function(){
            console.log('miao miao miao')
    }   
} 

obj1.method();
obj2.method();
黄舟
    var Cat = function(name) {
        this.name = name;
    }
    Cat.prototype.miao = function() {
        console.log("miao miao miao");
        var cat = new Cat("hahaha");
        setTimeout('cat.miao()', 1000);
    }

    var cat = new Cat("hahaha");
    cat.miao();

setTimeout的用法是:

setTimeout(function () {}, 1000); //or
setTimeout('func()', 1000);

而你的写法直接传入一下this.miao(),这样setTimeout是无效的,然而它会直接循环执行this.miao()

高洛峰

setTimeout 传入的是一个function,而你直接把function执行了。。。
也就是说,你在miao函数里面又调了miao,改成这么写就行了
刚才是this的指向问题,

setTimeout(this.miao.bind(this),1000);

PHPz

其实你这个直接是递归建立了无数setTimeout
应该

var Cat = function(name) {
    this.name = name;
}

Cat.prototype.miao = function() {
    console.log("miao miao miao");
    var _this = this; // 保存this引用 可以用es5 的bind 等技巧,
    // 另外 setTimeout('cat.miao()', 1000); 这个属于绝对调用 就是为了绑定正确的this
    setTimeout(function(){
       _this.miao()
    }, 1000);
}

var cat = new Cat("hahaha");
cat.miao();
高洛峰

比较懒的做法也可以直接用 arguments.callee 替代递归函数本身。

javascriptvar Cat = function(name) {
    this.name = name;
}

Cat.prototype.miao = function() {
    console.log("miao miao miao");
    setTimeout(arguments.callee, 1000);
}

var cat = new Cat("hahaha");
cat.miao();

巴扎黑

es6 es7 :: =>就会清晰多了
没必要为了以前的坑继续补,当然bind(this)也行

不过这里的问题是,你不知道引擎怎么执行的
你传一个 fn() 当参数,那么必然要执行fn才能知道return,所以他就一直执行咯.

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号