闭包 , 沙箱 ,

164 阅读3分钟

闭包

  • 闭包就是能够读取其他函数内部变量的函数
    • 闭包是指有权访问外层函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建一个内层函数,通过内层函数访问外层函数的局部变量,利用闭包可以突破作用链域
    • 闭包的特性:
      • 函数内再嵌套函数
      • 内部函数可以引用外层的参数和变量
      • 函数的执行空间不会被销毁
    function fun(n, o) {
      console.log(o);

      const obj = {
        fun: function (m) {
          return fun(m, n);
        },
      };

      return obj;
    }
 
    var a = fun(0); //undefined
    a.fun(1); //0
    a.fun(2); //0
    a.fun(3); //0
  • 闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。
    • 闭包 的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中
    • 使用闭包的注意点
      • 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,可能导致内存泄露
      • 解决方法: 在退出函数之前,将不使用的局部变量全部删除

沙箱模式

在前端编码中,或多或少都会接触到沙箱,学会使用沙箱,可以避免潜在的代码注入以及未知的安全问题。

沙箱,即sandbox,顾名思义,就是让你的程序跑在一个隔离的环境下,不对外界的其他程序造成影响,通过创建类似沙盒的独立作业环境,在其内部运行的程序并不能对硬盘产生永久性的影响。

    function outer() {
      let a = 100;
      let str = 'QF001';

      const obj = {
        getA: function () {
          return a;
        },
        getStr: function () {
          return str;
        },
        setA(val) {
          a = val;
        }
      }

      return obj;
    }

    // 1. 调用了外部函数outer , 这个函数内部会返回一个对象 obj, 存储到了变量res
    let res = outer();
    console.log(res);

    let num = res.getA();
    console.log(num);    // 100

    let newStr = res.getStr()
    console.log(newStr); // 'QF001'

    res.setA(999);
    console.log(res.getA()); // 999
    
    //同样,我们可以同样的方法重复多次的调用外部函数outer,这个函数内部同样会返回一个对象 obj,
    //我们可以任意去定义变量来存储这个对象

沙箱模式 计数器

1.html 书写页面结构

实现功能: 点击按钮,是实现数字的自增(自减)

  <button class="add1">+</button>
  <input type="text" class="inp1" value="1">
  <button class="sub1">-</button>

2.js 实现功能

//获取标签
    const add1 = document.querySelector('.add1')
    const inp1 = document.querySelector('.inp1')
    const sub1 = document.querySelector('.sub1')

2.1我们首先使用普通的方式实现

    let count = 1
    add1.onclick = function(){
      count++
      inp1.value = count
    }
    sub1.onclick = function(){
      count--
      sub1.value = count
    }

2.2 使用沙箱模式

    function outter(){
      let count = 1

      let obj = {
        getCount(){
          return count
        },
        setCount(value){
           count = value
        }
      }

      return obj
    }

    const res = outter()

    add1.onclick = function(){
      let max = res.getCount()
      res.setCount(max + 1)
      inp1.value =  res.getCount()
    }

    sub1.onclick = function(){
      let min = res.getCount()
      res.setCount(min - 1)
      inp.value = res.getCount()
    }

语法糖

语法糖: 其实就是在不影响功能的情况下,为我们提供了一些更加简单的方法 , 就是通过 gettersetter 帮助我们优化了一些操作和代码

下面通过代码来比较一下两者的区别

1.普通版

   function outter(){
      let count = 2

      return {
        getCount(){
          return count
        },
        setCount(value){
           count = value
        }
      }
    }

    let last = outter()
    let min = last.getCount()
    console.log(min)    //2
    last.setCount(520)  //重新设定值
    let max = last.getCount()//需要再次获取
    console.log(max)   //520

2.语法糖版

    function fn(){
      let a = 1

      return {
        get a(){
          return a
        },
        set a(value){       
           a = value
        }
      }
    } 

    let res = fn()
    console.log(res.a)//1
    res.a = 999       //重新设置 a 的值
    console.log(res.a)//999