JavaScript 闭包

JavaScript 闭包

做用域

  在Js中,全部的名字(变量/常量/函数/类)都有一个做用范围,这被称之为做用域。闭包

 

全局做用域


  全局做用域便是在全局下定义的名字做用范围,在Js中全局做用域中的名字全局有效,在任何做用域中都能进行访问。函数

 

  生命周期:页面打开则产生,页面完毕时销毁spa

  数量:最多只有一个code

 

image-20200731233734502

 

局部做用域


  局部做用域一般是指在函数中定义的名字做用范围,局部有效,外部不能访问。对象

 

  生命周期:对于函数的局部做用域来讲,函数调用时存活,调用完毕则销毁,也就是说每次调用函数都会新增一个局部做用域。函数执行完毕后该做用域将不复存在。blog

  数量:能够有多个局部做用域生命周期

 

image-20200731234314517

 

块级做用域


  块级做用域的范围小了不少,它只包含在{}中由let/const定义的名字的做用范围,也是局部有效,外部不能访问。ip

 

  生命周期:块级做用域是能够有多个的,生命周期为当执行块级做用域中代码块时块级做用域存活,执行完毕后块级做用域销毁。内存

  数量:能够有多个块级做用域作用域

 

image-20200731235222291

 

名字查找顺序


  先到自身的做用域中查找,若是没有再到定义本身做用域的做用域中进行查找。

 

image-20200731235914695

 

<script>"use strict";
​
        let username = "云崖";
​
        let age = 18;
​
        function show() {
​
​
                let username = "Yunya";  // 若是这里注释掉下面的查找结果是云崖
​
                let age = 16;
​
                console.log("show...");
​
                (function () {
​
                        console.log(username);  // Yunya
​
                }());
​
        }
​
        show();
​
​
</script>

 

块级做用域的封装


  在以前没有块级做用域这一律念以前进行模块封装都是使用自执行函数利用它函数局部做用域的特性进行封装,可是如今有了let/const块级做用域后咱们又有了新的封装方式。

 

  封装

{
​
        let show = function () {
                console.log("执行了show功能");
        }
​
        let test = function () {
                console.log("执行了test功能");
        }
​
        window.module = { show, test };
​
};

 

  调用

<script src="JavaScript.js"></script> 
<script>// 注意上面要引入模块
    
        "use strict";
​
        module.show();
        module.test();
​
</script>

 

闭包

  闭包其实很是简单,它是基于函数嵌套+做用域+函数参数进行实现的。

 

  闭:一个封闭的函数,不能被外部直接调用,因此该函数确定是在一个局部做用域或块级做用域中。

  包:一个包裹闭函数的函数被称之为包函数。

 

  咱们必定要注意一件事,即局部做用域的销毁是在函数执行完后进行销毁,可是这个销毁时机是有讲究的。

  若是咱们将局部做用域中的一个名字返回出去,那么该局部做用域的销毁时机是什么呢?这个得看状况。

 

  该名字指向的是一个值类型:当即销毁!值类型直接复制值就行了。

  该名字指向的是一个引用类型:不销毁!引用类型可能会被引用,你把局部做用域销毁了那块内存地址就空了,引用类型还引用个毛线。

 

<script>"use strict";
​
        function outer(){
​
                let username = "云崖";
​
                // 因为返回的是一个引用对象,故outer的做用域环境不会被销毁,若是销毁了内存地址清空就找不到这个
                // 函数了,因为outer的做用域环境不会销毁那么username也将会存活。
return function(){ 
​
                        console.log(username);  // 本身找不到,去上层找呗。而后找到了 云崖 
​
                }
​
        }
​
        let func = outer(); // func就是返回出来的匿名函数
        func();
​
</script>

 

闭包注意事项

  少用,少用。

  不销毁局部做用域表明不销毁这一块的内存,所以每作一个闭包函数一旦调用就会多出一块跟随全局做用域销毁的局部做用域,若是调用多了这个闭包函数那就emmm....

相关文章
相关标签/搜索