写点什么

JavaScript 闭包

作者:大熊G
  • 2022 年 6 月 12 日
  • 本文字数:1350 字

    阅读完需:约 4 分钟

JavaScript闭包

闭包是什么

做前端的可太需要了解闭包了,几乎每个面试都会问到闭包,闭包的重要性不言而喻。什么是闭包:闭包一般是指那些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。

function f1() {var a = 666;    function f2() {        console.log(a);    }    return f2; // f1返回了f2的引用}var jackson = f1(); // jackson就是f2函数了jackson(); // 执行jackson,全局作用域下没有a的定义,//但是函数闭包,能够把定义函数的时候的作用域一起记住,输出666
复制代码


复制代码上面的例子,首先有执行上下文 f1,在 f1 中定义了函数 f2,而通过对外返回 f2 的方式让 f2 得以执行。当 f2 执行时,访问了 f1 内部的变量 a。这个时候闭包就产生了。


闭包很有用,因为它允许将函数与其所操作的某些数据(环境)关联起来。这显然类似于面向对象编程。在面向对象编程中,对象允许我们将某些数据(对象的属性)与一个或者多个方法相关联。因此,通常你使用只有一个方法的对象的地方,都可以使用闭包。


this 对象

闭包中使用 this 会让代码变得复杂,之前的文章说过 this 指向问题,每个函数在被调用的时候都会自动创建俩个特殊变量:this 和 arguments。内部函数不可以直接访问外部函数的这俩个变量,但是可以把 this 保存到闭包就可以行得通。我们先看一下直接访问。

    window.identity = 'Jackson';    let obj = {        identity: 'bear',        getIdentityFunc() {            return function () {                return this.identity;            };        }    };    console.log(obj.getIdentityFunc()()); // 'Jackson'
复制代码

看一下把 this 保存到变量 that。

    window.identity = 'Jackson';    let obj = {        identity: 'bear',        getIdentityFunc() {            let that = this;            return function () {                return that.identity;            };        }    };    console.log(obj.getIdentityFunc()()); // 'bear'
复制代码

在定义匿名函数之前,先把 this 保存一下,在定义闭包时,可以让它访问 that,这是因为包含函数中名称没有任何冲突的一个变量。即使在外部函数返回后,that 仍然指向 obj。

因为闭包会保留他们包含的函数作用域,所以它比其他函数更占用内存,过度使用闭包而不释放的话就会导致过度占用。解决方法是,在退出函数之前,将不使用的局部变量全部删除,我们在之前讲过垃圾回收,点击查看(https://xie.infoq.cn/article/86ba7a784d4776994e6c5ec9c)

内存泄漏

在旧版本浏览器中,尤其是 ie,如果把 html 元素保存在闭包的作用域中,就相当于该元素不能被销毁。

    function clickaaa() {        let element = document.getElementById('aaa');        element.onclick = () => console.log(element.id);    }
复制代码

这里写了一个点击 aaa 元素,让它输出 aaa 的 id,只要这个函数存在,element 的计数就至少等于 1,也就是永远不会被回收。想让它回收的话我们在后面把它释放掉就可以了,大家一定要养成良好习惯。

    function clickaaa() {        let element = document.getElementById('aaa');        element.onclick = () => console.log(element.id);        element = null;//释放    }
复制代码


发布于: 刚刚阅读数: 5
用户头像

大熊G

关注

每天都在写bug的硬核男人 2022.06.02 加入

前端

评论

发布
暂无评论
JavaScript闭包_JavaScript_大熊G_InfoQ写作社区