js闭包、递归

闭包

  1. 闭包就是函数(简单理解为定义在一个函数内部的函数); 内层函数可以访问外层函数里面的变量

  2. 正常情况下, 函数调用结束后,函数内部的局部变量就会被销毁,但闭包不会销毁

  3. 闭包的作用,1. 可以在函数外面读取函数内部成员, 2. 让函数内成员始终存活在内存中

    <button>点击</button>
    <script>
      var button = document.querySelector('button');
    
      function fn() {
        var num = 10;
        return function () {
          num++;
          console.log(num);
        }
      }
      // fn() 调用结束后 内部的局部变量num应该被销毁
      // 但是这里产生了闭包, 让变量num一直保存在内存中,所以打印了10
      // 正常的情况下,函数一调用结束,里面的变量都会销毁,但闭包可以讲变量保存在内存里面
      // 学会调试功能,  看到clouser闭包的产生
      var f = fn();
      f();
      button.addEventListener('click', function(){
        f();
      })
    
    // 闭包应用-点击li输出当前li的索引号
    // 1. 我们可以利用动态添加属性的方式
    // 我们之前是利用自定义属性的发送 setAttribute('data-index', i)
    var lis = document.querySelector('.nav').querySelectorAll('li');
    for (var i = 0; i < lis.length; i++) {
       lis[i].index = i;
       lis[i].onclick = function() {
           // console.log(i);
           console.log(this.index);
       }
    }
    
    // 2.1 利用闭包的方式得到当前小li 的索引号
    for (var i = 0; i < lis.length; i++) {
     // 利用for循环创建了4个立即执行函数
     // 立即执行函数也产生了闭包,因为立即执行函数里面的任何一个函数都可以使用它的i这变量
     (function(i) {
         // console.log(i);
         lis[i].onclick = function() {
             console.log(i);
         }
     })(i);
    }
    
    //闭包在定时器中的应用
    for (var i = 0; i < 3; i++) {
     setTimeout(function () {
       console.log(i)
     }, 0)
    }
    
    for (var i = 0; i < 3; i++) {
     (function (index) {
       setTimeout(function () {
         console.log(index)
       }, 0)
     })(i)
    }
    

递归

  1. 函数内部自己调用自己, 这个函数就是递归函数

  2. 递归函数的作用和循环效果类似, 由于递归容易发生"栈溢出(stack overflow)"的错误, 所以一定注意加上退出条件

     // 利用递归函数求1~n的阶乘 1 * 2 * 3 * 4 * ..n
     function fn(n) {
         if (n == 1) {
             return 1;
         }
         return n * fn(n - 1);
     }
     console.log(fn(3));
    
    //利用递归求斐波那契数列  1、1、2、3、5、8、13、21...
    function fb(n) {
        if (n === 1 || n === 2) {
            return 1;
        }
        return fb(n - 1) + fb(n - 2);
    }
    console.log(fb(3));
    

    递归遍历数据,常用!!! 在一些框架的组件化开发中, 树形控件必须使用这种递归的写法

扩展—自己封装判断数据类型函数

var oP = Object.prototype,
toString = oP.toString;

function typeOf(value) {
    if (null === value) {
        return 'null';
    }

    var type = typeof value;
    if ('undefined' === type || 'string' === type) {
        return type;
    }

    var typeString = Object.prototype.toString.call(value);
    switch (typeString) {
    case '[object Array]':
        return 'array';
    case '[object Date]':
        return 'date';
    case '[object Boolean]':
        return 'boolean';
    case '[object Number]':
        return 'number';
    case '[object Function]':
        return 'function';
    case '[object RegExp]':
        return 'regexp';
    case '[object Object]':
        if (undefined !== value.nodeType) {
            if (3 == value.nodeType) {
                return (/\S/).test(value.nodeValue) ? 'textnode': 'whitespace';
            } else {
                return 'element';
            }
        } else {
            return 'object';
        }
    default:
        return 'unknow';
    }
}

猜你喜欢

转载自blog.csdn.net/qq_44879525/article/details/91038395