面试-闭包

发布于:2023-03-18 ⋅ 阅读:(527) ⋅ 点赞:(0)
  1. 什么是闭包

    需要说到作用域、作用域链、变量提升、暂时性死区、执行上下文等

作用域:

  • 一套变量放在哪,如何访问、修改的规则
  • 在 js 编译阶段,遍历作用域查当前的变量是否存在,如果存在就忽略该变量,继续下一个。如果不存在就在现在的作用域创建一个
  • 在执行阶段,会在当前作用域查找该变量,如果找不到会向父作用域查找,直到最外层
  • JS 中共有 3种作用域:

    • 全局作用域:定义在全局的变量拥有该作用域
    • 函数作用域:定义在函数内的变量拥有该作用域
    • 块级作用域:let、const 定义在 {} 中的变量拥有该作用域

作用域链:

  • 作用域之间存在嵌套关系,就形成了作用域链

闭包:

  • 在一个函数内存在,既不是函数参数,又不是函数的局部变量的变量,这个函数就是闭包

词法作用域和动态作用域

  • 词法作用域:作用域链沿着定义的位置延伸,js 之这种
  • 动态作用域:作用域链沿着调用栈延伸
  • js 中如何修改

    • eval: 把一段 string 转为 js 代码执行
    • width:会单独创建一个作用域
    • 决定不要用他们写代码
  1. 看代码说结果

    for (var i = 0; i < 5; i++) {
     setTimeout(function() {
         console.log(i);
     }, 1000);
    }
    
    结过:4个5
    原因:setTimout 延迟执行,定义的函数中没有 i,就会向外层作用域找,此时 i 已经是 5 了
    如何改造:
    -利用 setTimout 的第三个参数
    for (var i = 0; i < 5; i++) {
     setTimeout(function(j) {
         console.log(j);
     }, 1000, i);
    }
    -利用函数缓存变量
    for (var i = 0; i < 5; i++) {
     (function(j) {
       setTimeout(function() {
               console.log(i);
           }, 1000);
       })(i)
     
    }
    var a = 1;
    function test(){
     a = 2;
     return function(){
         console.log(a);
     }
     var a = 3;
    }
    test()();
    
    结果:2
    原因:var a = 3 的定义被变量提升了,test 内部的函数会用它作用域内的 a 变量,所以是2.要注意是 function 定义的位置找,不是使用的地方往外层找
    
  2. 应用

    • 实现私有变量:部分比较私密的变量,只想在对象内部生效,不能在外部访问
    • 实现偏函数、柯里化:可以实现将多个入参函数转为更少入参函数的方法

      function generateName(prefix, type, itemName) {
      return prefix + type + itemName
      }
      
      在使用时,第一个、第二个参数可能经常是固定的变量,这时就可以柯里化。
      function generateName(prefix) {  
      return function(type) {
       return function (itemName) {
           return prefix + type + itemName
       }    
      }
      }
      
      // 生成专属函数
      var countryName = generateName('中国')
      // 使用专属函数
      var cityName = countryName('广东')('广州')
      柯里化把所有的参数都分拆为一个,偏函数更加随意,可以差分为不同的个,例如:
      function generateName(prefix) {
      return function(type, itemName) {
       return prefix + type + itemName
      }
      }
      
      // 生成专属函数
      var countryName = generateName('中国')
      // 使用专属函数
      var cityName = countryName('广东','广州')
      
本文含有隐藏内容,请 开通VIP 后查看