马克思前端学习札记有意思的日记

一道js闭包面试题的学习

2018-08-18  本文已影响1人  dnaEMx

最近看到一条有意思的闭包面试题,但是看到原文的解析,我自己觉得有点迷糊,所以自己重新做一下这条题目。

闭包面试题原题

function fun(n, o) { // ① 
  console.log(o);
  return { // ② 
    fun: function(m) { // ③ 
      return fun(m, n); // ④ 
    }
  };
}

// 第一个例子
var a = fun(0); // 返回undefined
a.fun(1); // 返回 ?
a.fun(2); // 返回 ?
a.fun(3); // 返回 ?

// 第二个例子
var b = fun(0)
  .fun(1)
  .fun(2)
  .fun(3); //undefined,?,?,?

// 第三个例子
var c = fun(0).fun(1);
c.fun(2);
c.fun(3); //undefined,?,?,?

一、关于这个函数的执行过程

先大致说一下这个函数的执行过程:

① 初始化一个具名函数,具名函数就是有名字的函数,名字叫 fun。

② 第一个 fun 具名函数执行之后会返回一个对象字面量表达式,即返回一个新的object对象。

{  // 这是一个对象,这是对象字面量表达式创建对象的写法,例如{a:11,b:22}
  fun: function(m) { 
    return fun(m, n); 
  }
}

③ 返回的对象里面含有fun这个属性,并且这个属性里面存放的是一个新创建匿名函数表达式function(m) {}

④ 在③里面创建的匿名函数会返回一个叫 fun 的具名函数return fun(m, n);,这里需要说明一下这个 fun 函数返回之后的执行过程:

1. 返回 fun 函数,但默认不执行,因为在 js 里面,函数是可以保存在变量里面的。

2. 如果想要执行 fun 函数,那么首先会在当前作用域寻找叫fun 名字的具名函数,但是因为当前作用域里 fun 名字的函数是没有被定义的,所以会自动往上一级查找。
    2.1 注解:当前的作用域里是一个新创建的对象,并且对象里面只有 fun 属性,而没有 fun 具名函数
    2.2 注解:js 作用域链的问题,会导致他会不断地往上级链查找。

3. 在当前作用域没找到,所以一直往上层找,直到找到了顶层的 fun函数,然后执行这个顶层的 fun 函数。

4. 然后这两个 fun 函数会形成闭包,第二个 fun 函数会不断引用第一个 fun 函数,从而导致一些局部变量例如 n,o 得以保存。

所谓闭包:各种解释都有,但都不是很接地气,简单的来说就是在 js 里面,有一些变量(内存)可以被不断的引用,导致了变量(内存)没有被释放和回收,从而形成了一个独立的存在,这里涉及了js 的作用域链和 js 回收机制,结合两者来理解就可以了。

二、第一个例子的输出结果分析

1. var a = fun(0); // 返回 undefined

注解:

function fun(n, o) { // ① 
  console.log(o);  // 这里首先输出了  n 的值为undefined
  return { // ②  
    fun: function(m) { // ③ 
      return fun(m, n); // ④  
    }
  };
}

2. a.fun(1); // 返回 0

注解:

3. a.fun(2); // 返回 0

注解:

function fun(n, o) { // ① 
  console.log(o);
  return { // ② 
    fun: function(m) { // ③ 
      return fun(m, n); // ④ 
    }
  };
}

4. a.fun(3); // 返回 0

跟上面雷同,所以不做解释了。

二、第二个例子的输出结果分析

第二个例子其实是一个语句,只是进行了链式调用,所以会有一些不一样的处理。

1. 第一个返回 undefined

var b = fun(0) // 返回 undefined

注解:

2. 第二个返回 0

 fun(0).fun(1) // 返回 0

注解:

3. 第三个返回1

fun(0).fun(1).fun(2)

注解:

4. 第四个返回是2

跟第三个返回类似,所以不做解释了。

第三个例子的输出结果分析

// 这里已经无需多说了,跟第二个例子类似。
var c = fun(0).fun(1); // 返回 undefined 和0

1. 第三个返回是1,第四个返回是1

c.fun(2); // 第三个返回 1
c.fun(3); // 第四个返回 1

注解:


为了避免原文被吃掉,所以我这里保留了截图,并且加了一篇解释 js 闭包还不错的文章作为参考使用。

上一篇下一篇

猜你喜欢

热点阅读