文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

详细聊聊闭包在js中充当着什么角色

2024-04-02 19:55

关注

什么是闭包

开篇明义,概念先行。闭包是什么,为什么说在js中处处充满了闭包。

闭包就是函数有权访问另一个函数作用域中的变量,此函数和被引用的变量一起构成了闭包

文字描述文绉绉的难以理解,看一下代码就能够一目了然了

function test() {
    var a = 1
    var b = function() {
        console.log(a)
    }
    
    return b
}

在上面的代码例子中,变量 a 处于函数 test 的作用域中,但是函数 b 中可以对变量 a 进行访问。
套用闭包的概念,也就是函数 b 有权访问函数 test 作用域中的变量 a,此时函数 b 与变量 a 就形成了一个闭包。

看了上面的例子,大家是否恍然大悟,这不就是我们在代码中经常写的吗。所以说js中处处充满了闭包。

如何观察闭包

如果一开始我们对于闭包的认识还不是很深刻,我们怎么知道在代码中写出了一个闭包呢?一招教你找出闭包

function test() {
    let a = 1
    return function test1() {
        debugger
        console.log(a)
    }
}

test()()

如上的一段代码,在执行到 debugger 关键字的时候,我们可以打开浏览器的开发者调制工具,此时我们可以从调用栈中看到 Closure 的字样,这就是代表我们写出了一个闭包啦

闭包的错误认识

说完了闭包的概念,再来说说可能大家会对闭包产生的一些错误认识。

1.闭包的产生需要使用 return 暴露出去

首先从闭包的概念上来看就没有说到闭包需要暴露到函数外才叫闭包,而是只要引用了不属于当前函数作用域中的变量就已经产生闭包了。

为什么会有这样的错误认识,是因为我们使用闭包引用了外部作用域中的变量,一般是为了将这个变量或者是这个函数暴露出去,让我们在外部也可以访问到这个变量或者函数,也就是说将闭包暴露到函数外部只是我们的业务需求,而不是闭包的必要条件。

2.闭包会导致内存泄漏

首先我们要知道为什么闭包会导致内存泄漏,是因为我们将闭包暴露到函数外部的时候,闭包内部仍然引用着其外部作用域中的变量,导致外部作用域中的变量无法被垃圾回收机制回收,如果循环引用闭包的话就容易造成内存泄漏的现象。但这是由于我们在使用闭包过程中所引起的,而不是闭包本身的性质所决定的,因此说闭包一定会导致内存泄漏是不严谨的。

(另外在 IE9 之后也对浏览器的垃圾回收机制做了优化,现在已经不容易导致内存泄露了)

闭包导致的问题

作为 js 中八大陷阱之一的循环陷阱,就是由于闭包引起的

for (var i = 0; i < 4; i++) {
    setTimeout(() => {
        console.log(i)
    }, 1000)
}  // 4, 4, 4, 4

执行以上代码,会发现 1s 之后打印了 4个 4,为什么不是打印 0, 1, 2, 3,就是因为 setTimeout 中的回调函数是一个闭包,引用了外部作用域中的 i 变量,但是 i 只有一个,并不会在每个回调中生成新的 i,因此在 1s 后打印的时候访问的是同一个作用域中的 i 变量,因此打印的结果就是 4个 4

如何解决以上问题,有两个方法:

for (let i = 0; i < 4; i++) {
    setTimeout(() => {
        console.log(i)
    }, 1000)
}  // 0, 1, 2, 3
for (let i = 0; i < 4; i++) {
    (function(i) {
        setTimeout(() => {
            console.log(i)
        }, 1000)
    })(i)
}  // 0, 1, 2, 3

闭包的使用场景

说了这么多闭包的性质,甚至闭包还会引发循环陷阱这么重大的问题,那么闭包到底有什么用?面试官问到的时候总不能说 js 处处都是闭包,所以 js 到处都是闭包的使用场景吧。那么我们就来说说闭包的几个经典使用场景

1. 单例模式

var CreateSingleton = (function() {
    var instance = null
    var CreateSingleton = function() {
        if (instance) return instance
        return instance = this
    }
    return CreateSingleton
})()

单例模式是设计模式的一种,目的是为了保证全局中只有一个实例对象,上述代码利用 instance 创建一个闭包。单例模式在组件库保证全局中只有一个弹窗组件尤其好用。

2. 函数柯里化

柯里化是将一个多参数的函数转化成几个单参数的函数嵌套的形式,例如: function test(a, b, c) => function test(a)(b)(c)

function currying(fn, args) {
  var _this = this
  var len = fn.length
  var args = args || []

  return function() {
    var _args = Array.prototype.slice.call(arguments)
    Array.prototype.push.apply(args, _args)
    
    if(_args.length < len) {
      return currying.call(this, fn, _args)
    }

    return fn.apply(this, _args)
  }
}

3. 与立即执行函数配合使用完成类库的封装

闭包往往配合着立即执行函数来一起使用,能够发挥出强大的效果。因此,往往很多人容易被误导,认为闭包与立即执行函数之间有什么关系,甚至认为立即执行函数就是闭包。但这种认识其实是错误的,立即执行函数与闭包之间没有任何关系。

在 jQuery 盛行的年代,各类规范百花争艳,其中 umd 规范能够兼容多种环境,主要在于其 umd 头部结构的实现

(function( global, factory ) {
    "use strict";
    if ( typeof module === "object" && typeof module.exports === "object" ) {
        module.exports = global.document ?
        factory( global, true ) :
	function( w ) {
            if ( !w.document ) {
		throw new Error( "jQuery requires a window with a document" );
            }
            return factory( w );
	};
    } else {
	factory( global );
    }
})( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {})

以上这种代码的写法使用过 jQuery 开发的人应该非常熟悉吧。

4. 保存私有变量

在实际开发过程中,我们有时候需要对于计算结果进行缓存,或者是保存私有变量而不被外部访问到,就可以使用闭包来实现。

另外,在目前流行的两大前端框架 Vue 和 React 中其实也大量用到了闭包进行相关功能的实现,具体大家可以自己翻翻源码啦~

总结

到此这篇关于闭包在js中充当着什么角色的文章就介绍到这了,更多相关js中的闭包内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯