闭包与递归

一、闭包

闭包:就是一个函数可以访问另一个函数内的局部变量,这个访问者就被称呼为闭包
作用:就是延伸了变量的作用范围

1:闭包的两个方式

闭包的方式1:
    function fn() {
      let num = 10;
      function f2() { //f2是内部函数,一个闭包
        console.log(num); //使用了父函数中声明的变量  10
      }
      f2();
    }
    fn();
执行思路:fn-f2-把num变量被f2函数调用,输出log 结果为10

闭包的方式2:
    function fun() {
      let num = 20;
      // function fun1() {
      //   console.log(num); //这是一个闭包函数 ,调用了另一个函数的局部变量  20
      // }
      // return fun1; //返回的是一个函数 fun1
      //或者这样的更简洁
      return function () {
        console.log(num);
      }
    }
    let f = fun(); //由于调用fun函数,返回的是一个函数,用f来接收这个函数,并且调用f函数
    f();

2:闭包案例之循环点击事件

需求:利用闭包的方式,实现点击li输出索引号

  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
  let lis = document.querySelectorAll("ul li");
方式1:闭包的方式
    for (var i = 0; i < lis.length; i++) {
      //利用for循环创建3个立即执行函数  可以把i当做参数传递进去 因为i不在函数里面属于当前的i
      (function (i) {
        lis[i].addEventListener("click", function () {
          console.log(i);
        })
      })(i)
    }
    
方式2:forEach方法
    lis.forEach(function (v, i) {
      lis[i].addEventListener("click", function () {
        console.log(i);
      })
    })

3:闭包案例之定时器

需求:点击小li,2秒过后,打印对应的索引号
用到定时器

let lis = document.querySelectorAll("ul li");
1:用闭包的方式
    for (var i = 0; i < lis.length; i++) {
      (function (i) {
        lis[i].addEventListener("click", function () {
          setTimeout(function () {
            console.log(i);
          }, 2000)
        })
      })(i)
    }
    
2:用forEach方法
    lis.forEach(function (v, i) {
      lis[i].addEventListener("click", function () {
        setTimeout(function () {
          console.log(i);
        }, 2000)
      })
    })

4:闭包案例之简单的打车案例

需求:
  起步价13(3公里内),之后没加一公里就+5,用户输入输入公里数就可以计算打车价格
  如果拥堵的情况下,那么总价格加上10
思路:在立即执行函数里面,返回两个函数,分为正常的,还有拥堵的打车函数
      在拥堵的打车函数里面,需要判断是否拥堵,利用flag当做开关
    var car = (function () {
      let start = 13;
      let total = 0;

      return {
        price: function (n) {
          if (n > 3) {
            total = start + (n - 3) * 5;
          } else {
            total = start;
          }
          return total;
        },
        yd: function (flag) {
          return flag ? total + 10 : total;
        }
      }
    })()

    console.log(car.price(5)); //23
    console.log(car.yd(true)); //33
    console.log(car.price(1)); //13
    console.log(car.yd(false)); //13

5:思考题

    //思考题1:
    var name = "The Window";
    var Object = {
      name: "My Object",
      getNameFunc: function () {
        return function () {
          return this.name;
        }
      }
    }
    // console.log(Object.getNameFunc()());
    //解析
    // var f = object.getNameFunc();
    // // 类似于:
    // f = function () {
    //   return this.name;
    // }
    // f(); //最后输出的是f()函数

    // f()又类似于
    // function(){}() //立即执行函数 其中的this执行window
    //思考2:
    var name = "The Window";
    var object = {
      name: "The Object",
      getNameFunc: function () {
        var that = this; //这边函数中this指向是指向调用者
        return function () {
          return that.name;
        }
      }
    }
    console.log(object.getNameFunc()()); //The Object
    /*
    解析:
      // object.getNameFunc()()  可以拆分为下面两个,一个f函数,还有调用了f函数
      var f = object.getNameFunc(); //函数调用者为object
      // 而f函数又类似于
      f = function () { //由于函数调用者为object,所以输出的是object
        return that.name;
      }
      f();
    */

二、递归

递归:就是在函数内部调用本身,就是递归函数
注意点:使用递归容易发生栈溢出错误(stack overflow),所以必须添加退出条件

    //需求:我要打印6句话
    let num = 1;
    function fn() {
      console.log("我要打印6句话");
      if (num == 6) {
        return; //递归需要添加退出条件,否则变成了死递归
      }
      num++;
      fn();
    }
    fn();
    /*
    执行流程:
      外面fn调用函数---先打印--判断条件--num++---递归  到了num为6的时候,就直接退出,这类似while但是比它更香
    */

(1):递归求n!

需求:求123*…n的阶乘
思路:判断条件是当等于1的时候,返回1并且退出 返回的是:最后一项和最后两项相* (最后一项可以作为递归)

    let n = prompt("请输入n的值");

    function fn(n) {
      if (n == 1) {
        return 1;
      }
      return n * fn(n - 1);
    }
    fn(n);
    console.log(fn(n));

(2):利用递归求斐波那契数列(兔子序列) 1,1,2,3,5,8,13,21

需求:利用递归求斐波那契数列(兔子序列) 1,1,2,3,5,8,13,21
思路: 判断条件是:当n输入为小于等于2的时候,就返回1并且退出,规律:前面两项相加为第三项结果(因此可以这两项都为递归调用)

    let n = prompt("请输入n的值:")

    function fn(n) {
      if (n <= 2) {
        return 1;
      }
      return fn(n - 1) + fn(n - 2);
    }
    console.log(fn(n));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值