js中的闭包与定时器

1.什么是闭包?有什么作用?

闭包是指在 JavaScript 中,内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(执行结束被释放)了之后。

  • 闭包是指将函数外部的变量保存在函数内部,以备函数执行的时候可以访问,即使这个外部变量本身被释放了,在这个内部函数执行的时候依然可以访问,凡是实现这种功能的都可以称为闭包。闭包最明显的特征是在一个函数中return出一个函数,通过这个函数访问外部的变量,是实现封装的基础。
  • 维持了一个独立的数据空间,使得程序可以在函数外部访问局部变量,一般用于模块封装,但是闭包会带来内存泄漏的危险。

2.setTimeout 0 有什么作用

setTimeout 0是将函数的执行顺序移到代码的最后立即执行,即其他代码执行完后立即执行。

代码

  • 下面的代码输出多少?修改代码让fnArri 输出 i。使用两种以上的方法
    1
    2
    3
    4
    5
    6
    7
    var fnArr = [];
    for (var i = 0; i < 10; i ++) {
    fnArr[i] = function(){
    return i;
    };
    }
    console.log( fnArr[3]() ); //10

使用闭包实现:

1
2
3
4
5
6
7
8
9
10
var fnArr = [];
for (var i = 0; i < 10; i ++) {

fnArr[i] =(function(i){
return function(){
return i;
}
}(i));
}
console.log( fnArr[4]() ); //4

var fnArr = [];
for (var i = 0; i < 10; i ++) {

    fnArr[i] =(function(){
        var n=i;
          return function(){
            return n;
        }
    }());
}
console.log( fnArr[3]() );  //3
  • 使用闭包封装一个汽车对象,可以通过如下方式获取汽车状态

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    var Car = (function () {
    var speed;
    function setSpeed(s){
    speed = s;
    }
    function getSpeed () {
    console.log(speed);
    }
    function accelerate () {
    speed += 10;
    }
    function decelerate () {

    speed -= 10;
    if(speed<0){
    speed = 0;
    }
    }

    function getStatus () {
    if(speed>0){
    console.log("running");
    }else{
    console.log("stop");
    }
    }


    return {
    setSpeed:setSpeed,
    getSpeed:getSpeed,
    accelerate:accelerate,
    decelerate:decelerate,
    getStatus:getStatus
    }
    })();
    Car.setSpeed(30);
    Car.getSpeed(); //30
    Car.accelerate();
    Car.getSpeed(); //40;
    Car.decelerate();
    Car.decelerate();
    Car.getSpeed(); //20
    Car.getStatus(); // 'running';
    Car.decelerate();
    Car.decelerate();
    Car.getStatus(); //'stop';
    console.log(Car.speed); //undefined
  • 写一个函数使用setTimeout模拟setInterval的功能

    1
    2
    3
    4
    5
    6
    7
    function inter () {
    setTimeout(function () {
    console.log("每隔一秒输出一次");
    inter();
    },1000);
    }
    inter();
1
2
3
4
setTimeout(function inter () {
console.log("每隔一秒输出一次")
setTimeout(arguments.callee,1000);
},1000);
  • 写一个函数,计算setTimeout最小时间粒度

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var start = Date.now();
    var i=0;
    var delayer = setTimeout(function () {
    i++;
    if(i===1000){
    var end = Date.now();
    clearTimeout(delayer);
    console.log((end-start)/i);
    }
    setTimeout(arguments.callee, 0);
    },0);//4.1ms左右
  • 下面这段代码输出结果是? 为什么?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var a = 1;
    setTimeout(function(){
    a = 2;
    console.log(a);
    }, 0);
    var a ;
    console.log(a);
    a = 3;
    console.log(a);

输出1,3,2:

  1. 首先看执行过程var a声明了两次但均被前置,之后执行语句,a=1,setTimeout 0,则会放到代码的的最后去执行,接着执行console.log(a),此时 a=1,所以输出1;
  2. 执行语句a=3,console.log(a)将其输出为3;
  3. 代码执行完,立即执行setTimeout 0里面的函数,a=2,由于函数内部没有声明,去全局作用域找并赋值,console.log(a)输出2;
  • 下面这段代码输出结果是? 为什么?
    1
    2
    3
    4
    5
    6
    var flag = true;
    setTimeout(function(){
    flag = false;
    },0)
    while(flag){}
    console.log(flag);

j结果:死循环,因为setTimeout 0是放到整个代码的最后执行的,所以flag赋值为true后,执行while循环,因为flag=true,所以循环条件一直满足,也就是一直执行while,死循环

  • 下面这段代码输出?如何输出delayer: 0, delayer:1…(使用闭包来实现)
    1
    2
    3
    4
    5
    6
    for(var i=0;i<5;i++){
    setTimeout(function(){
    console.log('delayer:' + i );
    }, 0);
    console.log(i);
    }

0,1,2,3,4, 5个delayer:5
闭包实现:

1
2
3
4
5
6
7
8
for(var i=0;i<5;i++){
(function (i) {
setTimeout(function(){
console.log('delayer:' + i );
}, 0);
})(i);
console.log(i);
}

文章目录
  1. 1. 1.什么是闭包?有什么作用?
  2. 2. 2.setTimeout 0 有什么作用
  • 代码
  • ,