闭包和匿名函数

Posted 小数点就是问题

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了闭包和匿名函数相关的知识,希望对你有一定的参考价值。

在高级程序设计里,描述闭包是指有权访问另一个函数作用域中的变量的函数。

而经常创建方式是一个函数里包含另一函数。

而匿名函数就如“匿名”这两个意思一样。

所以匿名函数和闭包不是同一个概念。

在高级程序设计里描述匿名函数的执行环境具有全局性,所以this指向为window。这就是

为什么有时候发现this指向,不是自己所想的对象的问题。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        var name="a";
        var obj={
            name:"b",
            showFn:function(){
                return (function(){
                    return this.name;
                })();
            }
        }
        console.log(obj.showFn());
    </script>
</body>
</html>

打印结果为“a”

测试中可知:this指向window,所以才打印出“a”;

闭包:

简单的例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
     name="cde"; function a(){ var name="abc"; function b(){ alert(name); }; b(); } a(); </script> </body> </html>

然而使用画图更好理解:

 

 

 而这里的0表示自己的执行环境,1是上级执行环境,2是上上级执行环境,以此类推。

而变量查找是就近原则的,在自己最近的作用域查找到就会停止查找。

而这里活动对象的理解,很重要,因为只有函数在被调用时才是变量对象才是活动的,

才会去查找所要的变量。

如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        function a(){
            var name="abc";
            var arr=[];
            for(var i=0;i<4;i++){
                arr[i]=function b(){
                    alert(i);
                };
            }
            return arr;
            
        }
        a()[0]();
        a()[1]();
        a()[2]();
    </script>
</body>
</html>

弹出的结果都是4;

这是因为函数执行时内部函数没有在执行,而是内部函数执行完之后被调用时才执行,所以

这时活动对象上级作用域的变量都是同一一个值了;

还有闭包的执行环境结束了,活动对象也不会被销毁,这就像全局作用域,所以闭包里的变量是不会被

回收的,会一直保存着。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        function a(){
            var num=0;
            return function b(){
                num++;
                console.log(num);
            }
        }
        var m1=a();
        m1();
        m1();
        m1();
    </script>
</body>
</html>
结果:
1,,2,3

 

虽然使用闭包要谨慎;

但使用闭包可以避免全局污染的问题。

 

新扩充理解:

闭包:有权访问另外函数的作用域中的变量的函数

1、函数嵌套函数
2、内部函数可以引用外部函数的参数和变量

闭包内的变量是不会被垃圾回收机制回收

好处:
1、希望一个变量长期驻扎在内存当中
2、避免全局变量的污染
3、私有成员


用法:
模块化代码


内存泄漏就是关闭当前页面,变量还是占据内存,不释放,只有当浏览器关闭时才释放。这样很消耗cpu

测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<ul>
    <li>abc1</li>
    <li>abc2</li>
    <li>abc3</li>
    <li>abc4</li>
    <li>abc5</li>
</ul>
<div id="text"></div>
    <script>
        var aLi=document.querySelectorAll("ul li");
        var t=document.querySelector("#text");
        for(var i=0;i<aLi.length;i++){
            // 这里的i值都是5
            // aLi[i].onclick=function(){
            //     t.innerHTML=i;
            // }
            /*使用闭包的特性解决这个问题
                闭包的变量不会被释放,闭包可以访问外部函数的参数和变量
            */
            //(function a(){})括号括起来的是函数表达式
            //因为(function(){})()循环去执行这个,其实是循环创建函数
            //所以循环多少次就创建了多少个函数,就有多少个闭包
            // aLi[i].onclick=(function(i){
            //     return function(){
            //         t.innerHTML=i;
            //     }
            // })(i)
            //这也是一种方式,但也是使用了闭包的特性
            (function(i){
                aLi[i].onclick=function(){
                    t.innerHTML=i;
                }
            })(i)
        }
    </script>
</body>
</html>

 

以上是关于闭包和匿名函数的主要内容,如果未能解决你的问题,请参考以下文章

Golang中的匿名函数(闭包)

Go语言-make陷阱和闭包函数

14.匿名函数和闭包

自调用匿名函数(匿名闭包)解析与调用

自调用匿名函数(匿名闭包)解析与调用

php匿名函数和闭包函数及use关键字传参及Closure匿名函数类