zoukankan      html  css  js  c++  java
  • 一道闭包题题解

    题目来自 大部分人都会做错的经典JS闭包面试题

    很有意思的题目,切一发。

    function fun(n,o) {
      console.log(o)
      return {
        fun:function(m){
          return fun(m,n);
        }
      };
    }
    var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);//undefined,?,?,?
    var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?
    var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,?,?,?
    //问:三行a,b,c的输出分别是什么?
    

    先看第一组执行,fun(0) 后首先打印 undefined,没有问题。之后变量 a 便被赋值为 fun 函数所 return 的对象。即:

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

    这里要重点注意的是参数 n,值为 0,这就是闭包和作用域链。

    接着执行 a.fun(1) a.fun(2) a.fun(3),我们以 a.fun(1) 举例。a.fun(1) 的执行结果,因为没有赋值(其实有个 return value),所以其实就是执行了一遍 fun(m, n),上面说了,n 值为 0,所以控制台输出为 0。后两个输出同理。这里要注意的就是这个 n,因为作用域链,所以 n 能获取值,为 0,因为 n 被变量 a 所引用,所以它一直贮藏在内存中。

    再来看第二组,我们可以把它改成这样。

    var a = fun(0);
    var b = a.fun(1);
    var c = b.fun(2);
    var d = c.fun(3); 
    

    第一行,打印 undefined,没有问题,a 返回对象,然后执行 a.fun(1),打印 0,这些跟第一次的执行相同。a.fun(1),其实就是执行 fun(m, n),其实就是 fun(1, 0),return 的对象赋值给 b。

    var b = {
      fun: function(m) {
        return fun(m, n); // n=1
      }
    };
    

    类似的结果,唯一不同的是 n 的值变了,这是由 fun() 传入的参数所决定的。

    接下去,b.fun(2),执行 fun(2, 1),打印出 1,然后将 return 的对象赋值给 c。

    var c = {
      fun: function(m) {
        return fun(m, n); // n=2
      }
    };
    

    最后一步也是类似,所以依次打印 undefined, 0, 1, 2。

    最后看第三组。由第二组可得变量 c 的结果:

    var c = {
      fun: function(m) {
        return fun(m, n); // n=1
      }
    };
    

    然后执行过程和 1 类似,就不用多说了。

    综:个人认为这道题的 "恶心" 之处多数在于函数中调用函数本身(fun 函数中调用 fun 函数),而引起的思路混乱,其他部分其实跟下面代码类似,归根结底就是被引用的变量会始终存在在内存中。

    function fn() {
      var num = 0;
      return function() {
        console.log(num++);
      }
    }
    
    var a = fn();
    a();  // 0
    a();  // 1
    
    var b = fn();
    b();  // 0
    b();  // 1
    

    更多精彩分析可以参考原文。

  • 相关阅读:
    Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
    Python学习之字典详解
    IDEA启动服务慢的问题处理
    IDEA部署Tomcat应用所有接口中文乱码
    为什么选择微信公众号而不是小程序的考虑要素
    Vue基础及脚手架环境搭建
    VSCode集成Git代码管理
    VSCode开发工具下载
    U盘装系统:安装GHOST Win7系统教程
    前端资源管理工具sourcetree
  • 原文地址:https://www.cnblogs.com/lessfish/p/5092997.html
Copyright © 2011-2022 走看看