闭包和定时器

2017-01-18  本文已影响53人  sunny519111

setTimeout的语法

更新于2017年4月9号

setTimeout(func,time,params)  //一定time后,传入回调函数的参数params,并调用回调函数
setTimeout(func,time)  // 一定time后调用回调函数
setTimeout(code,time) //一定time后调用代码块(不推荐)

问题

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

闭包:一个变量,一个函数(环境),函数内部可以访问到这个变量就是一个闭包。
闭包的作用:1.可以访问函数内部的变量。2. 使变量可以一直保存在内存中。

2.setTimeout 0有什么作用

由于js的渲染机制是单线程序,无法同时执行多个不同的代码,当一个代码正在执行的时候,其他的代码都需要等待,直到正在运行的代码运行完后,才能运行下个等待的代码。所以一次点击事件,setTimeout,ajax异步请求都不是立刻的执行,而是立刻的排队。一旦线层空闲下来,就立刻执行。所以setTimeout 0不会立刻执行,而是排队等已经在执行的执行完,然后执行。

var c= 0 ;
function play(){
  console.log(c)
}
function add(){
  setTimeout(()=>{c+=1},100)
}

add()
play()
// 输出0
console.log(1)
setTimeout(function(){console.log},0)
console.log(3)
执行顺序
console.log('start')
setTimeout(function (){console.log("hello,200ms")},200)
setTimeout(function (){console.log("hello,100ms")},100)
console.log('end')
//start
//end
//hello,100ms
//hello,200ms
console.log('start')
setTimeout(function (){console.log("hello,200ms")},200)
for(var i=0;i<10000;i++){console.log(1)}
setTimeout(function (){console.log("hello,100ms")},100)
console.log('end')
//start
//10000个1
//end
//hello,200ms
//hello,100ms

setTimeout会被异步到另一个内存中,当程序流执行完成后,如果时间程序流运行完,setTimeout的时间还没有到,就谁最短谁就呈现然后再执行setTimeout的程序。

代码题

1.下面的代码输出多少?修改代码让fnArr[i]() 输出 i。使用两种以上的方法

    var fnArr = [];
    for (var i = 0; i < 10; i ++) {
        fnArr[i] =  function(){
            return i;
        };
    }
    console.log( fnArr[3]() );  //10

修改后

  1. 通过闭包来实现获取i
    var fnArr=[];
    for(var i=0;i<10;i++){
        fnArr[i]=function (n){
            var num =n;
            return function () {
                return num;
            }
        }(i)}
        console.log(fnArr[5]())

2.得不到i,无非就是你手速慢了,当你运行函数的时候,i的值就已经等于10了, 通过立即执行函数来获取i

    //第二种方法
    var fnArr=[];
    for(var i=0;i<10;i++){
        fnArr[i]=(function(){
            var obj ={};
            obj.i=i;
            return  obj.i
        })()
    }

    var fnArr=[];
    for(var i=0;i<10;i++) {
        (function(n){
            var num= n;
            fnArr[n] = function(){
                return num;
            }
        })(i)
    }

2. 使用闭包封装一个汽车对象

    var Car = (function () {
        var obj = new Object();
        obj.speed=0;
        obj.setSpeed=function (s) {
           obj.speed=obj.speed+s;
           return;
        }
        obj.getSpeed=function () {
            return obj.setSpeed;
        }
        obj.accelerate=function () {
           obj.speed=obj.speed+10;
           return
        }
        obj.decelerate =function (){
            obj.speed=obj.speed-10;
        }
        obj.getStatus =function (){
            if(obj.speed===0){
                return 'stop'
            }
            else{
                return 'running'
            }
        }
        return obj;
    })()

3.写一个函数使用setTimeout模拟setInterval的功能

    setTimeout(function sayHello(){
        console.log("hello");
        setTimeout(sayHello,1000);
    },1000)

拓展

具名函数,全局函数,局部函数的区别

  1. 具名函数 :setTimeout里面的函数就是具名函数,只能在setTimeout里面使用,如果在外部调用会报错。


    具名函数
  2. 全局函数:在任何的作用域都可以使用,就像window自带的方法和属性
  3. 局部函数:只能在其父元素的函数作用域中使用(闭包除外)
    局部函数

4.写一个函数,计算setTimeout平均最小时间粒度

让setTimeout执行1000次,然后我们除以执行的次数

    function  getMini2() {
        var now = Date.now();
        console.log(now);
        var i =0;
        var clock=setTimeout(function () {
           i++;
           if(i===1000){
               clearTimeout(clock);
               var fnow = Date.now();
               console.log((fnow-now)/i);
           }
           setTimeout(arguments.callee,0);
        },0)
    }

5.函数输出的内容

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.变量的声明前置。2.setTimeout的异步加载处理
由于setTimeout,所以匿名函数中的内容会在程序加载完成的空闲时间去执行,所以会被放到最后一个console.log(a)后执行。

6.输出结果分析

var flag = true;
setTimeout(function(){
    flag = false;
},0)
while(flag){}
console.log(flag);
//无限死循环,没有任何输出

Javascript引擎(JS引擎)是单线程的,在某一个特定的时间内只能执行一个任务,并阻塞其他任务的执行,也就是说这些任务是串行的。我们可以通过异步处理方法,当主线程在执行的过程中,异步处理的代码会被交到另一个模块去执行,当满足它执行的条件后,会被推到任务执行队列,在主线程全部加载完成,空闲下来后,就会去检查任务队列,执行里面的代码。
所以上面的setTimeout(function(){flag=false},0)会被最后执行,这样while就死循环了

7.下面这段代码输出?如何输出delayer: 0, delayer:1...(使用闭包来实现)

for(var i=0;i<5;i++){
    setTimeout(function(){
         console.log('delayer:' + i );
    }, 0);
    console.log(i);
}
//输出
//0,1,2,3,4 delayer: 5(5次)

分析

setTimeout(function(){
         console.log('delayer:' + i );
    }, 0);

上面一个代码块会在for(var i=0;i<5;i++),执行完后再执行,所以得到的i就是5

使用闭包输出delayer:0

    for(var i=0;i<5;i++){
        //我们把i传递到函数中
        (function(n){
            //用一个参数来接受它,然后返回一个函数调用这个参数
            var m = n;
            return setTimeout(function(){
                return console.log('delayer:' + m);
            },0)//通过setTimeout自动让它执行
        })(i)//立即执行它,得到几个函数
    }
上一篇下一篇

猜你喜欢

热点阅读