javascript函数式编程-------概念基础部分(闭包)

闭包

  • 闭包是一种机制,通过私有上下文来保护当中的私有变量;

        保护:当前上下文中的变量与其他上下文中的变量互不干扰

        保存:保存当前上下文中的数据(堆内存),被当前上下文以外的上下文中的变量所引用,这个数据就保存下来。

  • 也可以认为当我们创建的某个私有上下文执行完毕后,不能被释放的时候就形成了闭包;

函数和其周围的状态的引用捆绑在一起就形成了闭包,简单理解就是 ,一个作用域可以访问另外一个函数内部的局部变量。

可以在另一个作用域中(比如全局)调用这个函数内部的函数并访问到该函数作用域中的成员。

演示语法

首先我们定义一个makeFn的函数,在这个函数中定义一个变量msg,当这个函数调用之后,msg就会被释放掉。

function makeFn () {
    let msg = 'Hello';
    console.log(msg);
};
maknFn();

如果我们在makeFn中返回一个函数,在这个函数中又访问了msg,那这就是闭包函数。

和刚刚不一样的是,当我们调用完makeFn之后他会返回一个函数,接收的fn其实就是引用了makeFn返回的函数,也就意味着外部的fn对函数内部的msg存在引用。 所以当我们调用fn的时候,也就是调用了内部函数,会访问到msg,也就是makeFn中的变量。msg就不能被释放

所以闭包就是在另一个作用域(这里是全局),可以调用到一个函数内部的函数(makeFn内部返回的函数),在这个函数中可以访问到这个函数(makeFn)作用域中的成员。

所以说,闭包的核心作用就是把我们makeFn中内部成员的作用范围延长了,正常情况下makeFn执行完毕之后msg会被释放掉,但是这里因为外部还在继续引用msg,所以并没有被释放。

function makeFn () {
    let msg = 'Hello';
    return function() {
        console.log(msg);
    }
}
const fn = maknFn();
fn();

闭包的使用

这里有一个once函数,他的作用就是控制fn函数只会执行一次,那如何控制fn只能执行一次呢?这里就需要有一个标记来记录,这个函数是否被执行了,我们这里定义一个局部变量done,默认情况下是false,也就是fn并没有被执行。

在once函数内部返回了一个函数,在这个新返回的函数内部先去判断done,如果done为false,就把他标记为true,并且返回fn的调用。

当once被执行的时候,我们创建一个done,并且返回一个函数。然后我们通过pay变量指向这个函数, 也就是外部作用域对once函数内部有引用,once函数执行完毕后done不会被释放掉,当我们调用pay的时候,会访问到函数外部的done,判断done是否为false,如果是将done修改为true,并且执行fn。这样在下一次次调用pay的时候,由于done已经被 标记为true了,所以就不会再次执行了。

function once(fn) {
    let done = false;
    return function() {
        if (!done) {
            done = true;
            return fn.apply(this, arguments);
        }
    }
}

let pay = once(function(money) {
    console.log(`支付了${money}RMB`)
});

// 只会执行一次。
pay(10);
pay(20);
pay(30);

闭包的本质

函数在执行的时候会创建私有上下文然后入栈执行,当函数执行完毕之后会从执行栈上移除,但是堆上的作用域成员因为被外部引用不能释放,因此内部函数依然可以访问外部函数的成员。

这位老哥写的很不错,可以多看几遍http://caibaojian.com/js-closures-indeep.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值