4 回答
TA贡献1828条经验 获得超4个赞
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。
不知这样你是否清楚了。
TA贡献1802条经验 获得超6个赞
先是执行Cat()
这个函数,在对象中定义了say()
方法,接着遇到了setInterval
,这是个异步任务,所以加入到异步队列中。然后接着执行cat.say = function() {console.log('Hello'}
,这时,实例对象cat的的say方法已经被重写。接着,同步任务执行完了,执行之前加入异步队列中的回调函数,所以输出结果为Hello
.
TA贡献1780条经验 获得超5个赞
要输出'say something'关键要在定时器回调中运行Cat中o的确切引用,也可以这样:
var Cat = function() {
var another;
var o = {
say: function() {
console.log('say something');
}
}
another = o.say;
setInterval(function(){
another ();
}, 1000)
return o
}
TA贡献1797条经验 获得超6个赞
代码简化一下就是
var o = {
say: function() {
console.log('say something');
}
}
setInterval(function(){
o.say()
}, 1000);
var cat = o;
cat.say = function() {
console.log('Hello');
}
画个图:
o和Cat变量都指向0x0001地址,那里存放了一个对象;
对象上有一个say指针指向0x0002,那里是say函数;
后来,对这个say指针重新赋值,指向了0x0003地址,那是一个新的say函数;
最后,setInterval函数调用的是0x0003的say函数,而不是0x0002的say函数。
虽然setInterval的代码写在前面,但因为前三步都是同步任务,所以会先执行。
可以搜索一下JS的事件循环,同步任务代码先执行,setInterval和setTimeout这种宏任务会放在异步队列中等待同步任务完成后再执行。
添加回答
举报