闭包与循环的尝试
for(var i =0; i <= 5; i++) {
var old = new Date().getTime();
setTimeout(function timer() {
let newT = new Date().getTime();
console.log("time", newT - old);
console.log(i);
}, i * 1000);
}
输出结果:
time 6
6
time 1001
6
time 2002
6
time 3002
6
time 4001
6
time 5001
6
在上面的代码中,setTimeout对timer函数进行了引用,而timer函数对i进行了引用,回掉函数与i的变化是不同步的,i已经变到6的时候,可能timer函数还没有开始运行
for (var i=1; i<=5; i++) {
(function() {
setTimeout( function timer() {
console.log( i );
}, i*1000 );
})();
}
输出结果为:
6
6
6
6
6
6
虽然这里用到了自执行函数,但是和上面的原因是一样的
for(var i = 0; i < 5; i++) {
(function() {
var j = i;
setTimeout(function timeer() {
console.log(j);
}, j*1000);
})();
}
或是这样
for(var i = 0; i < 5; i++) {
(function(j) {
setTimeout(function timeer() {
console.log(j);
}, j*1000);
})(i);
}
结果:
0
1
2
3
4
在第一个中,由于自执行函数的存在,形成了一个块级作用域,在每次执行这个自执行函数的时候,j每次都是需要重新声明的,所以对于每一次的setTimeout中的j都是不一样的。
在第二种,给自执行函数传递了参数i,timeer函数中拥有自己的形参变量,所以每次的执行结果会不相同,虽然这两种的实现方式不太一样,但是基本的思路都是一致的,借助自执行函数,让每个timeer拥有不同的j或者是形参
for(var i = 0; i < 5; i++) {
let j = i;
setTimeout(function timer() {
console.log(j);
}, j*1000);
}
运行结果同上,对于let而言形成了一个块级作用域,所以每次的j也就是不同的了
for(let i = 0; i < 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i*1000);
}
for 循环头部的let声明有一个特殊的行为,这个行为指出变量在循环过程中不止被声明一次,每次迭代都会声明,随后的每个迭代都会使用上一个迭代结束的值来初始化这个变量
this
this
是一个语言中的关键字,this
这个对象是谁取决于函数被调用的方式,简单来说,就是“谁调用的,就是谁”
var obj = {
id : 'awesome',
cool: function foolCool() {
console.log(this.id);
}
}
var id = "not awesome";
obj.cool(); //awesome
setTimeout(obj.cool, 100); //not awesome
对于obj.cool()
,由于是obj
调用的cool
,则在cool
的内部,this
指代的就是obj
这个对象,所以this.id
输出的就是obj
的id
,也就是awesome
在setTimeout(obj.cool)
中由于setTimeout
对obj.cool
这个函数存在引用,形成了闭包,所以此时cool函数中的this也就是调用setTimeout的对象,就是window,所以输出的结果就是not swesome
保存this
var obj = {
count: 0,
cool: function coolFn() {
var self = this; //保存当前的this对象
if (self.count < 1) {
setTimeout( function timer(){
self.count++;
console.log( "awesome?" );
}, 100 );
}
}
};
obj.cool(); // 酷吧?
var obj = {
count: 0,
cool: function coolFn() {
if (this.count < 1) {
setTimeout( () => { // 箭头函数
this.count++;
console.log("this: ", this, "count: " , this.count);
}, 100 );
}
}
};
var count = -1;
obj.cool();
setTimeout(obj.cool, 100);
用当前的词法作用域覆盖了 this 本来的值
执行结果:
this: Object {count: 1, cool: function} count: 1
this: Window {stop: function, open: function, alert: function, confirm: function, prompt: function…} count: 0
var obj = {
count: 0,
cool: function coolFn() {
if (this.count < 1) {
setTimeout( function timer(){
this.count++; // this 是安全的, 因为 bind(..)
console.log(this.count);
}.bind( this ), 100 ); // look, bind()!
}
}
};
var count = -100;
obj.cool();
setTimeout(obj.cool, 100);
执行结果:
1
-99