面试专题总结:作用域和闭包

1,009 阅读3分钟

简介

拿到 字节跳动实习生offer 总结

回馈分享一波自己的知识点总结

希望读者依此构建自己的知识树(思维导图)

偷懒一下:可参考我自己总结思维导图 : 点这里

附带:高频面试题积累文档。 来自于(学长、牛客网等平台)

自己开发的博客地址:zxinc520.com

github地址: 点击

此篇 js - 【作用域和闭包】 知识点: 全部弄懂了,面试很容易。

一、作用域和作用域链概念

1.1、作用域

1.1.1、作用域是什么

作用域本质就是程序源代码中定义变量的区域,它可以解释为一套规则,是关于JS引擎如何寻找变量以及会在何处找到变量的规则。

1.1.2、作用域分为哪些

  • 词法作用域(静态作用域)
    • 词法作用域是在写代码时就确定了作用域(不使用eval和with的前提下,这两个现在基本不使用,因此不讲了),即静态作用域
  • 动态作用域
    • 而动态作用域是在代码运行时动态确定的

1.2、作用域链

1.2.1、作用域链是什么

作用域链实际上是指向变量对象的指针列表,它只引用但不实际包含变量对象,它的用途是保证对执行环境有权访问的所有变量和函数的有序访问。

简单来说:作用域链就是从当前作用域开始一层一层向上寻找某个变量,直到找到全局作用域还是没找到,就宣布放弃。这种一层一层的关系,就是作用域链。

两个重要概念:
  • 变量对象

    每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中(变量对象其实就是作用域这个抽象概念的具体值),比如一个函数中包含的局部变量,它的参数,它里面声明的函数都存在变量对象中。(一个当前执行函数的变量对象最开始时就包含一个arguments对象,这个对象用来装函数括号内的参数,所以全局环境的变量对象没有这个)

  • 执行环境

    也可以叫执行上下文,这里定义了变量或函数有权访问的其他数据,当一个函数被执行时,他的执行环境会被推入环境栈,执行之后才会被弹出,把控制权返回给之前的执行环境。

二、闭包

2.1、闭包是什么

闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包最常用的方式就是在一个函数内部创建另一个函数。

2.2、闭包的作用

  1. 能够访问函数定义时所在的词法作用域(阻止其被回收)。

  2. 私有化变量

  3. 模拟块级作用域

  4. 创建模块

    • 两个必备的条件(来自《你不知道的JavaScript》)
      • 必须有外部的封闭函数,该函数必须至少被调用一次(每次调用都会创建一个新的模块实例)
      • 封闭函数必须返回至少一个内部函数,这样内部函数才能在私有作用域中形成闭包,并且可以访问或者修改私有的状态。
    function coolModule() {
        let name = 'Yvette';
        let age = 20;
        function sayName() {
            console.log(name);
        }
        function sayAge() {
            console.log(age);
        }
        return {
            sayName,
            sayAge
        }
    }
    let info = coolModule();
    info.sayName(); //'Yvette'
    

2.3、闭包的缺点

闭包会导致函数的变量一直保存在内存中,过多的闭包可能会导致内存泄漏

2.4、经典题目(闭包)

函数自增

var fn =(function () {
    let i=0
    return function () {
        return i++
    }
})()
console.log(fn()) //0
console.log(fn()) //1
console.log(fn()) //2
console.log(fn()) //3