闭包与循环的尝试

来源:互联网 发布:股票交易软件 策略 编辑:程序博客网 时间:2024/05/18 03:22

闭包与循环的尝试

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(); //awesomesetTimeout(obj.cool, 100);  //not awesome

对于obj.cool(),由于是obj调用的cool,则在cool的内部,this指代的就是obj这个对象,所以this.id输出的就是objid,也就是awesome

setTimeout(obj.cool)中由于setTimeoutobj.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

原创粉丝点击