zoukankan      html  css  js  c++  java
  • 分享一道关于闭包的面试题,以及自己的理解

    这是一道经典的前端闭包的面试题,根据下面的函数,分别指出各打印的结果

    function fun (n,o) {
      console.log(o);
      return {
        fun: function (m) {
          return fun (m,n)
        }
      }
    }

    let a = fun(0)
    a.fun(1)
    a.fun(2)
    a.fun(3)

    let b = fun(0).fun(1).fun(2).fun(3)

    let c = fun(0).fun(1)
    c.fun(2)
    c.fun(3)

    解:结果应该是:undefined,0,0,0

            undefined,0,1,2

            undefined,0,1,1

    分析:

    第一部分:最外面的fun有两个参数,但只给了一个实参,所以fun函数内:n=0,o=undefined,因而fun(0)打印undefined(不管传入多少都打印undefined)。
    fun函数return一个对象,所以a指向这个对象:

    {

      fun:function(m){
        return fun (m,n)

      }

    }。

    a.fun(1)即为function(m){return fun (m,n)},且m=1,即a.fun(1)为fun(1,0)【0是之前传入的n】,由于在内部fun函数没有被定义,所以会沿着作用域链往外找,找到那个对象中的key值正好为fun,但是它没有两个参数,所以不匹配,继续往外找,一直找到最外面定义的fun函数,且有两个参数,找到了。所以a.fun(1)返回的就是最外面定义的那个函数,且根据形参的对应位置,把1赋给n,把0赋给o。所以a.fun(1)打印0。同样的原理,a.fun(2)即为fun(2,0),还是打印0,a.fun(3)同理。


    第二部分:fun(0).fun(1)相当于之前的let a=fun(0), a.fun(1),即先后输出undefined、0,重点是接下来的部分:我们已经知道fun(0).fun(1)即为a.fun(1)也就是fun(1,0),是一个对象,则fun(0).fun(1).fun(2)就是对象中fun所对应的值,即function(m) {return fun(m,n)},此时m为2,同样的,n为之前传入的1,返回的函数同样会沿着作用域链向上找,最终fun(0).fun(1).fun(2)就是fun(2,1),从而打印1。接着,fun(2,1)返回的是一个对象,所以fun(0).fun(1).fun(2).fun(3)就是对象中fun所对应的值,即function(m) {return fun(m,n)},此时m为3,同样的,n为之前传入的2,fun(0).fun(1).fun(2).fun(3)也就是fun(3,2)打印2。


    第三部分:undefined和0就不解释了,c就相当于第一部分中的a.fun(1)即fun(1,0),那么c.fun(2)就是第二部分中的fun(0).fun(1).fun(2),打印1,而c.fun(3)其实原理上是一样的,c是fun(1,0),返回一个对象,c.fun(3)就是function(m){return fun(m,n)},其中m=3,n=1,则c.fun(3)就是fun(3,1),打印1。

    第一条博客,能力有限,如有错误,欢迎指正

            

  • 相关阅读:
    CLR via C#(11)-无参属性、索引器
    CLR via C#(10)-参数
    C#委托的介绍(delegate、Action、Func、predicate)
    MVC3使用Unity实现接口自动注册
    CLR via C#(09)-扩展方法
    CLR via C#(08)-操作符
    CLR via C#(07)-静态类,分部类
    CLR via C#(06)- 构造器
    VS2010几款超赞的扩展辅助工具总结
    web前端开发随手笔记
  • 原文地址:https://www.cnblogs.com/Ryan368/p/11310224.html
Copyright © 2011-2022 走看看