资讯专栏INFORMATION COLUMN

闭包及其应用

alexnevsky / 2358人阅读

摘要:闭包带来的问题内存占用由于闭包使用其它函数内的变量,所以垃圾回收机制不会对闭包相关的函数进行回收,占用内存空间。

什么是闭包?

“在函数内使用其它函数内的变量,是为闭包”

【例1】
function a() {
    let num = 100;
    return function b() {
        console.log(num)
    }
}
var c = a()
c()   // 100

在例 1 中,a 为外层函数,a中返回了一个内部函数 b , 函数 b 中使用了 a 中的 num 变量。此时,函数 b 就形成了一个闭包。

闭包的用处是什么?

在JavaScript中,作用域链使得子作用域能够读取到父作用域的变量【见例2】,而反过来,父作用域无法直接获取子作用域的变量【见例3】。

【例2】
let num = 100
function a() {
    console.log(num)
}
a()   // 100



【例3】
function a() {
    let num = 100
}
console.log(num)   // error: not defined
当我们想在父作用域使用子作用域的值时该怎么办呢?

答:那就在函数内部再定一个函数,将其作为返回值即可【例4】。

【例4】
function a() {
    let num = 100
    return function b() {
        return num
    }
}
var x = a()
console.log(x())   // 100

例 4 中,函数 b 作为函数 a 的内部函数,可以访问 a 中的变量 num,于是我们将函数 b 作为返回值,我们通过操作 b 来访问 a 的变量。

上述利用闭包的特性来实现外部对内部的访问,便是闭包最基本的应用。

闭包的应用场景
1. 封装变量以控制权限

一般来说,我们只想让外界使用我们暴露出去的方法,而方法涉及到的变量计算想要封装在函数内部,以避免被有意/无意地修改变量值,此时,便可利用闭包来进行变量封装以控制权限【例5】。

【例5】
// 判断输入的变量是否是第一次输入
function isFirstVisit() {
    let _list = []
    return function (id) {
        if (_list.indexOf(id) >= 0) {
            console.log("Exist!")
        } else {
            _list.push(id)
            console.log("Added~")
        }
    }
}
let firstVisit = isFirstVisit()
firstVisit(5)   // Added~
firstVisit(5)   // Exist!
firstVisit(10)   // Added~

将 isFirstVisit 的返回值赋给 firstVisit ,然后通过使用 firstVisit 进行判断,因为暴露给外界使用的是 firstVisit 函数,所以只能使用该函数定义的方法,而无法对 _list 进行任何修改,保证了数据的私密性。

2. 函数柯里化

函数柯里化就是把一个函数接收多个参数进行处理,转变为接收单一参数,然后返回一个新函数接收下一个参数【见例6】。

【例6】
// 普通函数
function sum(x, y) {
    return x + y
}
// 函数柯里化
function curryingSum(x) {
    return function(y) {
        return x + y
    }
}

这里函数柯里化后的内部函数所使用的 x,就是其父作用域的变量,此时的内部函数就是一个闭包。

函数柯里化应用之 参数复用
【例7】 
function check(reg, txt) {
    return reg.test(txt)
}

// 检验是否含有数字
check(/d+/g, "test")   // false
check(/d+/g, "abc")   // false
check(/d+/g, "2dd")   // true

// 柯里化后
function curryingCheck(reg) {
    return function(txt) {
        return reg.test(txt)
    }
}

let hasNumber = curryingCheck(/d+/g)

hasNumber("test")      // false
hasNumber("abc")   // false
hasNumber("2dd")   // true

通过上例可以看到,直接使用check函数,第一个参数“正则判断语句”在每次使用时都需要输入,既不美观也不方便。对其进行函数柯里化后,只需输入一次正则判断语句,便可对判断函数进行复用。

闭包带来的问题
内存占用

由于闭包使用其它函数内的变量,所以垃圾回收机制不会对闭包相关的函数进行回收,占用内存空间。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/104309.html

相关文章

  • JavaScript基础系列---闭包及其应用

    摘要:所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。所以本文中将以维基百科中的定义为准即在计算机科学中,闭包,又称词法闭包或函数闭包,是引用了自由变量的函数。 闭包(closure)是JavaScript中一个神秘的概念,许多人都对它难以理解,我也一直处于似懂非懂的状态,前几天深入了解了一下执行环境以及作用域链,可戳查看详情,而闭包与作用域及作用域链的关系密不可分,所...

    leoperfect 评论0 收藏0
  • 作用域链、垃圾回收机制、闭包及其应用(oop)

    摘要:执行环境变量对象活动对象作用域链执行环境,为简单起见,有时也称为环境是中最为重要的一个概念。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。闭包垃圾回收机制先介绍下垃圾回收机制。 执行环境、变量对象 / 活动对象、作用域链 执行环境(executioncontext,为简单起见,有时也称为环境)是JavaScript中最为重要的一个概念。执行环境定义了变量或函数有...

    EastWoodYang 评论0 收藏0
  • JS之闭包及其作用

    摘要:如上述代码所显示,闭包是需要函数套函数,其实只是因为我们需要局部变量,否则此变量就会变成全局变量,无法隐藏。闭包的作用可以间接调用函数内部的局部变量。 前言 闭包作为JS中的一大难点,相信许多小伙伴也常常为此疑惑,闭包到底是什么?它有什么用呢? 变量作用域 在学习闭包之前,你必须清楚知道JS中变量的作用域。JS中变量的作用域无非就全局变量和局部变量,两者之间的关系是函数内部可以直接访...

    junnplus 评论0 收藏0
  • 详解js闭包

    摘要:但闭包的情况不同嵌套函数的闭包执行后,,然后还在被回收闭包会使变量始终保存在内存中,如果不当使用会增大内存消耗。每个函数,不论多深,都可以认为是全局的子作用域,可以理解为闭包。 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。 闭包的特性 闭包有三个特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变量不会...

    Chiclaim 评论0 收藏0
  • Django Web开发技术栈清单-Python基础篇

    摘要:使用单引号双引号和三引号或来表示字符串。不可变的集合函数会以字典类型返回当前位置的全部全局变量。用于将进制整数转换成进制,以字符串形式表示。返回字符串中最大的字母,或数组中的最大值。的作用就是减少了单行函数的定义。 问题答案由本人整理 1.基础语法是否熟悉?介绍一下 Python和其他语言最大的区别就是使用行和缩进,而不是大括号({})或者分号(;)来控制类、函数或者逻辑判断。Pyt...

    leeon 评论0 收藏0

发表评论

0条评论

alexnevsky

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<