闭包与循环的尝试

闭包与循环的尝试

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输出的就是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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值