美文网首页饥人谷技术博客
前端基础(问答15)

前端基础(问答15)

作者: 郑哲明 | 来源:发表于2016-07-21 22:36 被阅读53次

    keywords: 闭包、定时器。


    • 什么是闭包? 有什么作用

    内层函数调用外层函数的变量,该内层函数即为闭包。本质上,闭包是将函数外部和函数内部的作用域链接起来的桥梁。

    比如:

    //在全局中访问函数的局部变量
          function f1(){
            var n=999;
            function f2(){
              return n;
            }
            return f2;
          }
          var result=f1();
          result(); // 999
    

    作用:1、读取函数的内部变量;
    2、将这些变量的值始终保存在内存。

    举例说明闭包的作用:

      function f1(){
        var n=999;
        nAdd=function(){n+=1}
        function f2(){
          console.log(n);
        }
        return f2;
      }
      var result=f1();       //此时,result即为f2函数;同时,result是全局变量,
      result(); // 999        //调用f2函数,此时n为999
      nAdd();                   //nAdd为全局变量,可以在函数外部调用;同时nAdd既是匿名函数,又是闭包,此时n=1000
      result(); // 1000      //调用f2函数,此时n为1000
    

    可以看到,f1的变量n一直保存在内存中,并没有随f1调用后清除。
    为什么变量n不被清除呢? 这是因为f2作为全局变量result保存下来,同时f2依赖于f1的存在,f1也就始终保存在内存中。

    参考:
    学习JavaScript闭包
    解释JavaScript的作用域和闭包

    • setTimeout 0 有什么作用

    setTimeout(fn,0)会把fn放在代码最后执行。
    例如:

    console.log(1); 
    setTimeout(function(){ console.log(2);}, 0);
     console.log(3);
    //1
    //3
    //2
    

    参考:
    定时器

    • 代码

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

    var fnArr = []
    for (var i = 0; i < 10; i ++) {     //for循环,完成10次赋值操作
        fnArr[i] = function() {
            return i
        }  //此时function未执行
    }       //for循环执行完毕,i===10
    console.log(fnArr[3]())
    //为什么上述代码没有实现预期目的?
    //关键在于for循环中的function的 i 没有随for改变
    //因此有如下方案:
    
    ===========方法一===================
        
    for (var i = 0; i < 10; i ++) {
        fnArr[i] =(function(i) {
            return function () {
                return i
            }
            console.log(i)
        })(i)
    }
    
    ===========方法二===================
    
    for (var i = 0; i < 10; i ++) { 
        (function (i) {
            fnArr[i] = function() {
            return i
        }
      })(i)
    }  
    
    
    • 使用闭包封装一个汽车对象,可以通过如下方式获取汽车状态

    
    var Car = (function () {
        var speed = 0
        function setSpeed(spd) {
            speed = spd
        }
        function getSpeed(){
             console.log(speed)
        }
        function accelerate() {
             speed += 10
        }
        function decelerate () {
            speed -= 10
        }
        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';
    //Car.speed;  //error
    
    
    • 写一个函数使用setTimeout模拟setInterval的功能

    
    
    function intv(fn, time) {
        setTimeout(function () {
            intv(fn, time)
            fn()
        },time)
    }
    
    
    function test() {
        console.log(1)
    }
    
    intv(test,1000)
    
    • 写一个函数,计算setTimeout最小时间粒度

    (function testMini(){
        var i = 1
        var start = new Date()
        var clock = setTimeout(function(){
            i++
            if(i === 1000){
                clearTimeout(clock);
                var stop=new Date();
                console.log((stop-start)/i);
            }
            else {
                var clock = setTimeout(arguments.callee,0);
            }
        },0)
    })()
    
    • 下面这段代码输出结果是? 为什么?

    var a = 1;
    setTimeout(function(){
        a = 2;
        console.log(a);
    }, 0);
    var a ;
    console.log(a);
    a = 3;
    console.log(a);
    
    // 1
    // 3
    // 2
    //setTImeout中的代码会在后面代码执行完毕后再执行
    
    • 下面这段代码输出结果是? 为什么?

    var flag = true;
    setTimeout(function(){
        flag = false;
    },0)
    while(flag){}
    console.log(flag);
    
    //卡死在while无限循环
    
    //因为setTimeout会在后面代码执行完毕后再执行,实际代码如下:
    //var flag = true;
    //while(flag){}
    //console.log(flag);
    //setTimeout(function(){
    //    flag = false;
    //},0)
    
    • 下面这段代码输出?如何输出delayer: 0, delayer:1...(使用闭包来实现)

    for(var i=0;i<5;i++){
       (function (i) {
         setTimeout(function(){
             console.log('delayer:' + i );
        }, 0)
    
    })(i)
           console.log(i)
    }
    
    
    

    相关文章

      网友评论

        本文标题:前端基础(问答15)

        本文链接:https://www.haomeiwen.com/subject/cnkbjttx.html