JS高级(函数深刻理解2)

一、闭包(clsure)

1. 变量作用域

  • 变量分为全局变量和局部变量
  • 函数内部可以使用全局变量
  • 函数外部不可以使用局部变量
  • 当函数执行完毕,当前作用域内的局部变量会销毁

2. 闭包的意义

 闭包指有权访问另一个函数作用域中变量的函数

  • 一个作用域可以访问另外一个函数内部的局部变量
  • 变量所在函数就是闭包函数
     
  •  断点调试可以验证闭包出现情况

    • 当未进入fn函数内部就是全局作用域
    • 进入fn就是局部作用域
    • 在调用fu进入就产生闭包
    • fn存在调用变量就是闭包函数

JS高级(函数深刻理解2)_第1张图片

 

 3. 闭包的作用

 主要作用:延申变量的可用范围

 4. 闭包的案例

动态添加属性:闭包不一定存在优势

  
    
    

 闭包定时器:最后实现同步任务

    
    
    
   

 出租打表计时器:

  • 起步:13(3km内)
  • 增加1km + 5¥
  • 拥堵多收10¥
        var car = (function fn() {
        // 此时的total和start都是局部变量
        var start = 13; //起步价
        var total = 0; //总价
        return {
          //正常总价
          price: function (n) {
            if (n <= 3) {
              total = start;
            } else {
              total = start + (n - 3) * 5;
            }
            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(5)); //23
      console.log(car.yd(false)); //23

 5. 判断是否出现闭包

  • 未产生闭包

      var name = "The Window"; //这个名字挂在window之下
      var object = {
        name: "My Object",
        getNameFunc: function () {
          return function () {
            return this.name;
          };
        },
      };
      console.log(object.getNameFunc()()); //The window(未产生闭包)

以上的代码调用可以分解成下面的函数调用

       var f = getNameFunc();
      // 函数一调用就会生成返回值(就是下面的函数)
      var f = function () {
        return this.name; //此处作为普通函数访问全局变量
      };
      f();
        function(){this}()//立即执行函数:指向的还是window
  •  产生闭包

       var name = "The Window";
      var object = {
        name: "My Object",
        getNameFunc: function () {
          var that = this; //此时this指向的是object
          return function () {
            return that.name;
          };
        },
      };
      console.log(object.getNameFunc()()); //My Object

6. 总结闭包

  • 闭包是一个函数(一个作用域可以访问另外一个函数的局部变量)

  • 闭包的作用:延申了变量的作用范围

二、递归

1. 什么是递归?

如果一个函数在内部可以调用其本身,那么这个函数就是递归函数

简单理解:函数内部自己调用自己,这个函数就是递归函数

    

2. 递归的问题:

  • 递归的作用和循环的效果是一样

  • 由于递归很容易出现栈溢出,所以必须添加退出条件 

JS高级(函数深刻理解2)_第2张图片

 

    

3. 递归的使用

利用递归求阶乘

    

斐波那契数列

  • 数列规律:前两项之和等于后面一项的值:1,1,2,3,5,8,13,21,,,

  • 案例效果:输入参数获得响应的兔子序列值

    

检验以下第五个参数的计算 

 

JS高级(函数深刻理解2)_第3张图片 

 实例:根据选取细分的商品对象

  • 首先遍历数组数据
  • 相同数组元素id的就赋值给空对象
  • 否则:数组对象存在商品元素并且对象的商品元素有多个
  • 再次调用遍历数组
   

 三、浅拷贝、深拷贝

节点处耳闻深拷贝浅拷贝

  • 此处是对对象的拷贝

1.  浅拷贝

    var obj = {
      id: 1,
      name: "nihao",
      // 对象深层数据
      msg: {
        age: 18,
      },
    };

此处是拷贝的数据

     //ES5中遍历对象方法拷贝
    var o = {};
    for (var k in obj) {
      //k是属性名,obj[k]是属性值
      o[k] = obj[k];
    }
    //ES6  浅拷贝语法糖
    var o = {};
    Object.assign(o, obj);
 o.msg.age = 20; //此处修改o对象中的对象那个数据中内容同样会修改拷贝源的数据

 

JS高级(函数深刻理解2)_第4张图片

JS高级(函数深刻理解2)_第5张图片

 

2. 深拷贝(使用递归)

 

       var obj = {
        id: 1,
        name: "nihao",
        msg: {
          age: 18,
        },
        color: ["pink", "red"],
      };

拷贝数据

    //   封装函数
    function deepCopy(newobj, oldobj) {
        for (var k in oldobj) {
          // 1.获取属性值 oldobj[k]
          var item = oldobj[k];
          //2. 判断这个是值是否是数组
          //  判断数据值类型
          if (item instanceof Array) {
            newobj[k] = [];
            deepCopy(newobj[k], item);
          } else if (item instanceof Object) {
            //3.判断这个值是否是对象,是的话执行深度拷贝
            newobj[k] = {};
            deepCopy(newobj[k], item);
          } else {
            //4.属于简单类型
            newobj[k] = item;
          }
        }
      }
    //调用深拷贝
    var o = {};
    deepCopy(o, obj);
    console.log(o);
    var arr = [];
    console.log(arr instanceof Object);

JS高级(函数深刻理解2)_第6张图片

 

你可能感兴趣的:(java,开发语言)