javascript setInterval回调函一点疑惑

本人新手, 学习javascript定时器的时候遇到了一点疑惑, 可能是个老生常谈的问题了, 但是还是想请教一下各位前辈, 问题与代码如下:

var Cat = function() {
    var o = {
        say: function() {
            console.log('say something');
        }
    }
    setInterval(function(){
        o.say()
    }, 1000)
    return o
}

var cat = Cat()

cat.say = function() {
    console.log('Hello');
}

问题描述:
我定义了一个Cat类(用的工厂模式), 然后这个类里面有一个方法say(), 同时还有一个setInterval执行这个'方法', 然后实例化这个类, 重新声明一次say()这个方法.

我的困惑:
在于, 输出是'Hello', 而不是我一开始定义的那个类里面的那个方法, 这个地方不是特别理解

个人理解:
由于setInterval传进来的回到函数是一个方法, 实际上那个 o 指代的是实例化以后的那个实例对象, 而不是一开始的那个类?

但是感觉好像有点懂了, 但是又有点不懂, 或者其实根本不懂, 到底该如何正确清晰理解这段代码的运行过程, 希望各位前辈能有一个详细的解答, 多谢.

阅读 1.4k
评论
    4 个回答
    • 2.6k

    o本来就是实例化后的对象,你每执行一次Cat,就会有一个新的o生成。o的实例化在执行完var o = ...后就完成了。

    试运行以下代码:

    var Cat = function() {
        var o = {
            say: function() {
                console.log('say something');
            }
        }
        let say = o.say;
        setInterval(function(){
            say();
        }, 1000)
        return o
    }
    
    var cat = Cat()
    
    cat.say = function() {
        console.log('Hello');
    }

    这时输出就是

    Say something

    这个问题其实和setInterval无关,你提供的代码中的setInterval的回调函数持有的是对o这个实例的引用,而不是对o.say的引用,因此一秒后这个回调执行的时候,就会先找到o,然后再去找o.say;而我提供的代码中的setInterval的回调函数持有的是对o.say这个函数的引用,并且是对旧的o.say的引用,因此一秒后这个回调执行的时候,就会直接找到旧的o.say

    不知这样你是否清楚了。