第3章 第3节 闭包(JavaScript闭包和闭包面试题)

1.函数作用域

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>JavaScript闭包属性详解</title>
    </head>
<body >
<div id="div1" style="height: 100px;background: red;"></div>
</body>
</html>
<script type="text/javascript">
   var n=99;
   function outer() {
       var n=0;
       alert(n);
       }
   document.getElementById("div1").onclick=outer();
 </script>

运行结果:
在这里插入图片描述
访问的n是outer函数内部的不是全局的n,作用域链原理,先访问自己作用域的,没有才顺着链向上一层层找,直至找到,否则报错,找不到变量。

在这里插入图片描述

2.计数器,记录点击次数

第一种方法:这是使用全局变量实现,全局变量常驻内存,一直保存着

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>JavaScript闭包属性详解</title>
</head>

<body>
    <div id="div1" style="height: 100px;background: red;"></div>
    <div id="div2" style="height: 100px;margin: 10px;   background: green;"></div>
</body>

</html>
<script type="text/javascript">
    var n = 99;

    function outer() {

        return ++n;
    }

    document.getElementById("div1").onclick = function() {
        this.innerHTML = outer();
    }
</script>

在这里插入图片描述
第二种方式推导:全局变量使用总害怕其他地方有冲突,一直常驻内存,占用资源等弊端。

第1步骤:在outer函数内加n变量

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>JavaScript闭包属性详解</title>
</head>

<body>
    <div id="div1" style="height: 100px;background: red;"></div>
    <div id="div2" style="height: 100px;margin: 10px;   background: green;"></div>
</body>

</html>
<script type="text/javascript">
    var n = 99;

    function outer() {
        n=0;
        return ++n;
    }

    document.getElementById("div1").onclick = function() {
        this.innerHTML = outer();
    }
</script>

在这里插入图片描述
结果每次单击出现的结果都是一样的。因为每次单击调用outer函数时候,作用域中会重新创建一个n变量,而且n=0都要执行一次
第2步骤:如何让这个n保存在内存,且不重置值。考虑到作用域链,如果这个outer函数内部还有一个inner()函数,这个内部函数调用outer()的变量,那么JavaScript是不会回收这个变量n的。

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>JavaScript闭包属性详解</title>
</head>

<body>
    <div id="div1" style="height: 100px;background: red;"></div>
    <div id="div2" style="height: 100px;margin: 10px;   background: green;"></div>
</body>

</html>
<script type="text/javascript">
    var n = 99;

    function outer() {
        n = 0;

        function inner() {
            return ++n;
        }
    }

    document.getElementById("div1").onclick = function() {
        this.innerHTML = outer();
    }
</script>

在这里插入图片描述

但显示打印的是undefined。运行查看发现单击调用的是outer(),它的函数体内没有返回值,
第3步骤:考虑到js中函数也可像变量一样当参数和返回值,所以把inner()整体做返回值,不但保留的n变量在作用域链,同时返回自加值。

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>JavaScript闭包属性详解</title>
</head>

<body>
    <div id="div1" style="height: 100px;background: red;"></div>
    <div id="div2" style="height: 100px;margin: 10px;   background: green;"></div>
</body>

</html>
<script type="text/javascript">
    var n = 99;

    function outer() {
        n = 0;

        return function inner() {
            return ++n;
        }

    }

    document.getElementById("div1").onclick = function() {
        this.innerHTML = outer();
    }
</script>

在这里插入图片描述
但返回的是在这里插入图片描述
函数体,所以要在返回前,把函数赋给某个变量,得到结果
第4步骤:添加变量

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>JavaScript闭包属性详解</title>
</head>

<body>
    <div id="div1" style="height: 100px;background: red;"></div>
    <div id="div2" style="height: 100px;margin: 10px;   background: green;"></div>
</body>

</html>
<script type="text/javascript">
    var n = 99;

    function outer() {
        var n = 0;
        return function inner() {
            return ++n;
        }
    }

    var counter = outer(); //outer()函数执行返回的就是inner()函数

    document.getElementById("div1").onclick = function() {
        this.innerHTML = counter(); //所以执行counter()函数就是执行inner()函数,inner()函数有的作用域链,counter()函数也能同样保留。
    }
</script>

在这里插入图片描述

在这里插入图片描述
这样外部函数counter通过调用inner访问到了outer里定义的n;
外部函数调用内部函数的变量,或者平辈函数调用另一个函数的变量。都称为闭包。
在这里插入图片描述

很类似:你同学要借你爸的车用,做法却是约你去郊游。

3.两个计数器,记录点击次数

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>JavaScript闭包属性详解</title>
</head>
<body >
<div id="div1" style="height: 100px;background: red;"></div>
<div id="div2" style="height: 100px;margin: 10px;   background: green;"></div>
</body>

</html>
<script type="text/javascript">
    var n=99;
    function outer() {
        var n=0;
        return function inner() {
            return ++n;
        }
    }

    var counter=outer();

    document.getElementById("div1").onclick=function () {
        this.innerHTML=counter();
    }

    var counter2=outer();
    document.getElementById("div2").onclick=function () {
        this.innerHTML=counter2();
    }
</script>

在这里插入图片描述
counter()和counter2(),虽然都把outer()赋给他,但各做各的,counter()和counter2()各自在内存中引起建立两套不同的outer()和它内部的n和inner。

在这里插入图片描述

如何形象的理解这个内容呢?
我们可以以篮球投篮类比:

function  投篮(){
        记分牌=0计分变量=function 投进(){
                记分牌=记分牌+2}
        return   计分变量;
}

单击div=function 投篮();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

szmtjs10

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

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

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

打赏作者

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

抵扣说明:

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

余额充值