js深入学习之闭包

119 阅读3分钟

高阶函数

一个函数如果接收另一个函数作为参数,或者该函数会返回另一个函数作为返回值的函数,那么这个函数就被称之为高阶函数。

function foo(n, m, calc) {
    console.log(calc(m, n))
}

function add(m, n) {
    return m + n
}

foo(1, 2, add) // foo即为高阶函数



function foo() {
    function bar() {
        console.log('bar')
    }
    return bar
}
var fn = foo() // foo即为高阶函数
fn()

数组的相关方法:filter(过滤),map(映射),forEach(迭代),reduce(累加),find(查找) ,findIndex等都是高阶函数。

reduce

reduce接受两个参数,第一个是一个函数,第二个是初始值。如下图所示代码,实现了对nums数组的求和。preValue是上一次计算结果的值,item是当前数组元素。

var nums = [1, 3, 6, 8, 10, 11]
var val = nums.reduce((preValue,item)=> {
    return preValue + item
}, 0)
console.log(val)

闭包

闭包和函数最大的区别在于,当捕捉闭包式,它的自由变量会在捕捉时被确定,这样即使脱离了捕捉的上下文,它也能照常运行。

如以下代码,是如何执行的呢?

function foo() {
    var name = 'believe'

    function bar() {
        console.log('bar', name)
    }

    return bar
}

var fn = foo()
fn()

1、编译代码,在内存中创建一个全局变量,全局变量包括 foo,fn。如下图 image.png 2、接下来执行代码,创建一个函数对象,同时在调用栈中加入 foo函数执行上下文。

image.png

3、执行foo函数,在函数变量中给name赋值,同时返回bar函数地址赋值给fn变量。 image.png 4、执行完foo函数后,销毁对应的函数执行上下文。

image.png

5、接下来执行bar函数,创建函数执行上下文。 image.png

6、执行输出操作,发现当前作用域内没有name变量,沿着作用域链向上寻找,在foo的函数变量中,找到name并输出。 image.png

因为bar函数引用了name变量(name即自由变量),造成foo执行上下文被销毁后,对应的AO变量未被销毁,这个时候闭包就形成了。

简而言之,闭包由两部分组成:函数(bar)+可以自由访问的变量(name

内存泄漏

正常代码执行流程

function foo() {
    var name = 'believe'
    var age = 18
}

foo()

以上代码的执行,如下图,在执行完foo函数后,对应的函数执行上下文被销毁,此时对应的AO对象也应该被销毁。

image.png

在执行代码时才会创建AO对象。

闭包代码

function foo() {
    var name = 'believe'
    var age = 20

    function bar() {
        console.log(name, age)
    }

    return bar
}

var fn = foo()
fn()

执行完foo函数中,各指向如下图,销毁foo的执行上下文,GO对象中的fn指向foo的AO对象,所以foo的AO对象不会被销毁。

image.png 接下来执行fn()

image.png

fn()执行之后销毁对应上下文,其对应的AO对象也被销毁,但是foo的AO对象不会被销毁。 fn执行完毕之后,foo的AO对象是没有意义的,就被称为内存泄漏(该被回收的东西没有被回收)。

image.png

那怎么解决内存泄漏呐??

function foo() {
    var name = 'believe'
    var age = 20

    function bar() {
        console.log(name, age)
    }

    return bar
}

var fn = foo()
fn()
fn = null // 解决内存泄漏
foo = null // 解决内存泄漏

在使用完fn后,将fnfoo释放,即可解决。

本文是学习王元红老师深入JavaScript高级语法课程的个人总结,素材来源于课程。