JavaScript 闭包

458 阅读2分钟

闭包


导航

  • 前置知识
  • 什么是闭包
  • 闭包的用途
  • 闭包的缺点

前置知识

  • JavaScript在声明函数或者变量时,会赋予其相应的作用域,有全局作用域,函数作用域以及let/const要注意的的块级作用域

  • 示例(1)

//全局作用域
let a =1;
console.log(a); // 1
function b(){
    a=2 // 修改了全局变量
}
b();
console.log(a) // 2
  • 示例(2)
//块级作用域
let a =1;
console.log(a) // 1
function b(){
    let a=2// 局部变量
}
b();
console.log(a) // 1
  • 示例(3)
//函数作用域
let a = 1;
console.log(a); // 1
function b() {
    let a = 2;
    function c() {
        a = 3; 
    }
    c()
    console.log(a); // 3
}
b();
console.log(a); // 1  全局变量未被污染

一、什么是闭包

  • 定义

    • 首先看一下百度百科的介绍:闭包就是能够读取其他函数内部变量的函数。例如在javaScript中,只有函数内部子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

    • 所以我们总结一下,并换一种更好理解的方式——闭包就是一个函数引用了另一个函数作用域内的变量

  • 示例(4)

function check(color) {
    let ban1 = 'orange';
    let ban2 = 'red';
    function noEntry() {
        if (color === ban1 || color === ban2) {
            console.log('体温不正常')
        } else {
            console.log('体温正常')
        }
    }
    return noEntry;
}
check('green');

二、闭包的用途

  • 根据定义我们可以知道,闭包是在嵌套函数中经常会用到的一种方法。比如示例(4)中,调用变量的函数noEntry被定义在另一个函数check的作用域内。

  • 根据下面的例子我们就可以看出闭包的用途

    • 1.避免污染全局变量影响后续代码
    • 2.可以访问函数内部变量
let a = 1;
console.log(a); // 1
function b() {
    let a = 2;
    let e = 3;
    function c() {
        a = 3;
    }
    c()
    console.log(a); // 3
}
b();
console.log(a); // 1  全局变量未被污染
console.log(e); // ReferenceError: e is not defined ; e未定义无法访问函数内部变量

三、闭包的缺点

  1. 由于闭包会保留它们包含函数的作用域,所以会比其他的函数更占用内存。
  2. 正常函数作用域会在执行完它的全部代码后释放内存(压栈,弹栈),在一些情况下,闭包的活动对象并不能在它执行完后释放
function a() {
    let b = 1;
    function c() {
        b = 2;
    }
    c();
    return b;
}
a()
let e = a();
console.log(typeof (e)); // number
console.log(e); // 2 变量b的内存没有被释放 供函数C调用


笔者目前刚刚学习一个月,出错再所难免,欢迎指正。