闭包的理解

闭包的概念

闭包函数:声明在一个函数中的函数,叫做闭包函数。

闭包:内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回了之后。

闭包是有权限访问其他函数作用域的局部变量的一个函数

由于在JS中,变量的作用域属于函数作用域,在函数执行后作用域就会被清理、内存也随之被收回,但是由于闭包是建立在一个函数内部的子函数,由于其可访问上级作用域的原因,即使上级函数执行完,作用域也不会随之销毁,这时的子函数—也就是闭包,便拥有了访问上级作用域中的变量的权限,即使上级函数执行完后,作用域内的值也不会被销毁。

闭包的特点

  • 让外部访问函数内部变量成为可能;
  • 局部变量会常驻在内存中;
  • 可以避免使用全局变量,防止全局变量污染;
  • 会造成内存泄漏(有一块内存空间被长期占用,而不被释放)
  • 函数内部嵌套函数
  • 闭包的this指向window

闭包的创建

闭包就是可以创建一个独立的环境,每个闭包里面的环境都是独立的,互不干扰。**闭包会发生内存泄漏,每次外部函数执行的时候,外部函数的引用地址不同,都会创建一个新的地址。**但凡是当前活动对象中有被内部子集引用的数据,那么这个时候,这个数据不删除,保留一根指针给内部活动对象。

闭包内存泄漏为:key = valuekey被删除了value常驻内存中;局部变量闭包升级版(中间引用的变量)=> 自由变量。

闭包解决了什么问题

在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

由于闭包可以缓存上级作用域,那么就使得函数外部打破了“函数作用域”的束缚,可以访问函数内部的变量。
以平时使用的 AJAX 成功回调为例,这里其实就是个闭包,由于上述的特性,
回调就拥有了整个上级作用域的访问和操作能力,提高了极大的便利。
开发者不用去学钩子函数来操作上级函数作用域内部的变量了。

闭包的应用场景

闭包随处可见,一个 Ajax 请求的成功回调,一个事件绑定的回调方法,一个 setTimeout 的延时回调,或者一个函数内部返回另一个匿名函数,这些都是闭包。简而言之,无论使用何种方式对函数类型的值进行传递,当函数在别处被调用时,都有闭包的身影。

结论:闭包找到的是同一地址中父级函数中对应变量最终的值。

demo1:

function funA () {
    var a = 10; // funcA的活动对象之中

    return function () { // 匿名函数的活动对象
        alert(a)
    }
}
var b = funA()
b()  // 10

demo2:

function outerFn() {
    var i = 0;
    function innerFn() {
        i++;
        console.log(i)
    }
    return innerFn;
}

var inner = outerFn()  // 每次外部函数执行的时候, 都会开辟一块内存空间,外部函数的地址不同,都会重新创建一个新的地址
inner()
inner()
inner()
var inner2 = outerFn()
inner2()
inner2()
inner2()
// 1 2 3 1 2 3

demo3:

var i = 0
    function outerFn() {
        function innerFn() {
            i++
            console.log(i)
        }
        return innerFn
    }

    var inner1 = outerFn()
    inner1()
    inner1()
    inner1()

    var inner2 = outerFn()
    inner2()
    inner2()
    inner2()

    // 1 2 3 4 5 6

demo4:

function fn() {
    var a = 3;
    return function() {
        return ++a;
    }
}
alert(fn()());   // 4
alert(fn()());   // 4

demo5:

function  outerFn() {
    var i =  0;
    function innerFn() {
        i++;
        console.log(i)
    }
    return innerFn
}

var inner1 = outerFn()
var inner2 = outerFn()
inner1();  // 1
inner2();  // 1
inner1();  // 2
inner2();  // 2

demo6:

(function(){
    var m = 0;
    function getM() {
        return m;
    }
    function setA(val) {
        m = val;
    }
    window.g = getM;
    window.f = setA;
})();

f(100);
console.log(g())  // 100 闭包找到的是同一地址中父级函数中对应变量最终的值

demo7:

function a() {
    var i = 0;
    function b() {
        alert(++i);
    }
    return b;
}

var c = a();
c(); // 1
c(); // 2

demo8:

function f() {
    var count = 0;
    return function() {
        count++;
        console.info(count)
    }
}
var t1 = f()
t1();
t1();
t1();
// 1 2 3

demo9:

var add = (x) => {
    var sum = 1;
    var temp = (x) => {
        sum = sum + x;
        return temp;
    }
    temp.toString = () => {
        return sum
    }

    return temp;
}
alert(add(1)(2));  // 3

alert(add(1)(2)(3));  // 6

demo10:

<body>
    <ul>
            <li>Lorem ipsum dolor sit.</li>
            <li>Est illo vitae porro!</li>
            <li>Enim magnam tempora sed.</li>
            <li>Assumenda, optio. Ex, incidunt?</li>
    </ul>
</body>
<script>
   var lis = document.getElementsByTagName("li");
   for(var i = 0; i< lis.length; i++) {
        (function(i) {
            lis[i].onclick = function() {
                console.log(i)
            }
        })(i); /// 事件处理函数中闭包的写法
   }

   // 0 1 2 3

</script>

demo11:

const m1 = () => {
    var x = 1;
    return function () {
        console.log(++x)
    }
}

m1()();  // 2
m1()();  // 2
m1()();  // 2

var m2 = m1()
m2();  // 2
m2();  // 3
m2();  // 4

demo12:

var fn = (function () {
    var i = 10;
    function fn() {
        console.log(++i);
    }

    return fn;
})()

fn();
fn();

demo13:

function love1() {
    var num = 223;
    var me1 = function () {
        console.log(num)
    }
    num++;
    return me1;
}

var loveme1 = love1()
loveme1();  // 224

demo14:

function fun(n, o) {
    console.log(o);
    return {
        fun: function (m) {
            return fun(m, n)
        }
    }
}

var a = fun(0); undefined
a.fun(1); 0
a.fun(2); 0
a.fun(3); 0

var b = fun(0).fun(1).fun(2).fun(3); // undefined 0 1 2

var c = fun(0).fun(1);
c.fun(2);
c.fun(3);  // undefined 0 1 1 

demo15:

function fn() {
    var arr = []

    for (var i = 0; i < 5; i++) {
        arr[i] = function () {
            return i
        }
    }
    return arr;

}

var list = fn();
for (let i = 0, len = list.length; i < len; i++) {
    console.log(list[i]())
}
// 5 5 5 5 5 

demo16:

function fn() {
    var arr = []

    for (var i = 0; i < 5; i++) {
        arr[i] = (function (i) {
            return function () {
                return i;
            }
        })(i)
    }
    return arr;

}

var list = fn();
for (let i = 0, len = list.length; i < len; i++) {
    console.log(list[i]())
}
// 0 1 2 3 4
  • 30
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Joyce Lee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值