var data = [];
for(var i = 0; i < 3; i ++) {
data[i] = (function(i) {
return function() {
console.log(i);
}
}(i))
}
data[0]();
data[1]();
data[2]();
答案:0 1 2
function fun(n, o) {
console.log(o);
return {
fun : function(m) {
return fun(m, n);
}
};
}
var a = fun(0);//这里第一次调用fun时输出undefined,返回了一个对象给a, n=0
a.fun(1);//这里首先调用了a对象的属相fun,属性fun,又调用了一个闭包函数,m = 1,返回一个fun(1,0)
//执行fun(1,0),输出0,且又返回了一个对象
//console.log(typeof(a.fun(1)));//object
a.fun(2);//返回的就是fun(2,0) //0
a.fun(3);//返回的就是fun(3,0) //0
var b = fun(0).fun(1).fun(2).fun(3)//fun(0)返回的是fun(0,0),fun(1)返回的是fun(1 , 0),输出0,这时n=1,fun(2)返回的是fun(2,1),输出1,这时n=2,fun(3)返回的是fun(3,2),输出2,这是n=3;
var c = fun(0).fun(1); //undefined 0
c.fun(2); //1
c.fun(3);//1
function fn1() {
for(var i = 0; i < 4; i ++) {
var tc=setTimeout(
function(i){
console.log(i);
console.log(tc);
clearTimeout(tc)
}, 10 ,i);
}
}
fn1();
延迟10ms后执行的function(i),i的值是保存在第一个计时器执行的值。
而tc得值早就更新为创建第4个计时器返回得值。
第一次执行function(i)得时候,就清除了最后一个计时器,最后一个计时器根本没有执行
这道题主要考察了异步和闭包的问题
异步:js是单线程的,一次只能执行一个命令。js在执行时会生成一个主任务队列(先进先出),队列里按照顺序执行,当执行到setTimeout时,setTimeout会将里面的函数放到异步队列中,当 setTimeout执行完以后,js通过eventloop事件循环,发现异步队列中有任务等待,于是将其添加到队i列中开始执行.
所以tc最后保留的是创建最后一个计时器返回的值(tc = 4)之后才开始执行setTimeout里面的函数function(i)
闭包:即使setTimeout执行结束,但已经对内产生了闭包,当再执行function时使用的值的环境,仍然对应当时创建计时器执行时的作用域链,而tc没有被保留在闭包中,所以第一次cleartimeout(tc)时,就把最后一个计时器清除了,导致根本没有执行最后一setTimeout,所以输出得结果为 0 1 2
function fn2() {
for(var i = 0; i < 4 ;i ++){
var tc=setInterval(function(i, tc){
console.log(i);
clearInterval(tc)
},10,i,tc);
}
}
每间隔10Ms,执行一次function(i,tc),tc得值也被保留在闭包中(创建一个计时器得环境中)
清除计时器在这里第一个值为undefined,i为1时才清除第一个计时器
使得保留最后一个计时器,每隔10ms就输出3。