Skip to content
On this page

JS闭包

  1. 下面的代码打印了什么?为什么?
js
function daRio() {
  let name = "剑大瑞"
  let callMe = function(bilibili) {
    return bilibili + name
  }
  return callMe
}

daRio()("帅哥")
  1. 当JavaScript引擎在执行代码之前会经历哪三个步骤?
  2. 创建变量时发生了什么?
  3. 改造下面的代码,使之输出0 - 9,写出你能想到的所有解法
js
for (var i = 0; i< 10; i++){
  setTimeout(() => {
     console.log(i);
  }, 1000)
}
  1. 请写出如下代码的打印结果
js
var name = 'Tom';
(function() {
    if (typeof name == 'undefined') {
      var name = 'Jack';
      console.log('Goodbye ' + name);
    } else {
      console.log('Hello ' + name);
    }
})();
  1. 下面的题目打印结果是什么,如果想输出1,2,3怎么实现?
js
var data = [];
    
    for (var i = 0; i < 3; i++) {
      data[i] = function () {
        console.log(i);
      };
    }
    
    data[0](); 
    data[1]();
    data[2]();
  1. 何谓自由变量?
  2. 闭包的弊端?

1、JS引擎在执行代码之前会经历哪三个步骤?

图解

在上面这个过程中其实有三个角色相互配合,分别是Javascript引擎大哥、编译器老二、作用域保姆。

  • JS引擎负责整个JS代码的编译及执行
  • 编译器负责进行语法分析及代码生成
  • 作用域根据一套非常严格的家规(「规则」)收集并维护变量一系列的查询,确定谁有权限访问谁。

2、创建变量时发生了什么?

图解

首先编译器会在当前作用域中声明一个变量(如果之前没有声明过),然后在运行在时JS引擎会在作用域中查找(作用域链查找)该变量,如果能找到就对变量进行赋值

3、闭包

闭包就是基于JavaScript的**「词法作用域」,当嵌套函数在外部环境执行的过程中通过「作用域链」**访问到包含它的函数作用域中变量所形成的一种现象。并且由于嵌套函数存在对包含函数变量引用的原因,导致外部作用域中的变量无法及时销毁,会占用一定的内存。如果闭包过多,则会影响程序性能。

闭包的另一种定义

如果一个函数引用了自由变量,那么该函数就是一个闭包。何谓自由变量?自由变量是指不属于该函数作用域的变量(所有全局变量都是自由变量,严格来说引用了全局变量的函数都是闭包,但这种闭包并没有什么用,通常情况下我们说的闭包是指函数内部的函数)。

js
// 简单的缓存工具
// 匿名函数创造了一个闭包
const cache = (function() {
  const store = {};

  return {
    get(key) {
      return store[key];
    },
    set(key, val) {
      store[key] = val;
    }
  }
}());
console.log(cache) //{get: ƒ, set: ƒ}
cache.set('a', 1);
cache.get('a');  // 1

闭包的形成条件

  • 存在内、外两层函数
  • 内层函数对外层函数的局部变量进行了引用

闭包的用途

可以定义一些作用域局限的持久化变量,这些变量可以用来做缓存或者计算的中间量等。

  • 模块化
  • 柯里化 Currying

闭包的弊端

持久化变量不会被正常释放,持续占用内存空间,很容易造成内存浪费,所以一般需要一些额外手动的清理机制。