zoukankan      html  css  js  c++  java
  • javascript中的闭包

    一、什么是闭包

      函数在定义时的 词法作用域 以外的地方被调用,就会产生闭包。

    二、产生闭包的原因

      都是因为 词法作用域 造成的。无论通过何种手段将内部函数传递到所在的词法作用域以外,它都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包,且使得该作用域能够一直存活,没办法进行垃圾回收。

     function foo(){
                let a = 1;
                function bar(){
                    console.log(a);
                }
                return bar;
            }
    
            const f = foo();
            //这就是闭包(原本bar()是存在foo()作用域里的,外部不能返回,但现在foo()外部也能访问)
            f();    //1
    
    
            for(var i=0;i<5;i++){
                //与我们设想结果不一样的原因: 所有的回调函数依然是在循环结束后才会被执行,因此会每次输出一个5 出来。
                setTimeout(()=> console.log(i),0);  //5 5 5 5 5 
            }
    
            //所以,上面的代码等价于
            for(var i=0;i<5;i++){}
            setTimeout(()=> console.log(i),0);        //5
            setTimeout(()=> console.log(i),0);        //5
            setTimeout(()=> console.log(i),0);        //5
            setTimeout(()=> console.log(i),0);        //5
            setTimeout(()=> console.log(i),0);        //5
    
            //解决方法1:运用IIFE创建闭包作用域
            for(var i=0;i<5;i++){
                (function(j){
                    setTimeout(()=> console.log(j),0);  //0 1 2 3 4
                })(i);
            }
            //解决方法2:使用let,生成块作用域
            for(let i=0;i<5;i++){
                setTimeout(()=> console.log(i),0);  //0 1 2 3 4
            }

    三、应用

    1、在定时器、事件监听器、Ajax请求、跨窗口通信、Web Workers或者任何其他的异步(或者同步)任务中,只要使 用了回调函数,实际上就是在使用闭包!

    2、模块

    function foo(){
                let a = 1;
                function bar(){
                    console.log('foo bar');
                }
                return {a, bar};    //返回含有对内部函数的引用的对象
            }
    
            //创建模块实例
            const f = foo();
            f.bar();    //foo bar      这就是闭包
    //模块管理器的原理(单例模式)
            var MyModules = (function Manager(){
                var modules = {};
                function define(name, deps, impl){
                    for(var i=0; i<deps.length; i++){
                        deps[i] = modules[deps[i]];
                    }
                    modules[name] = impl.apply(impl, deps);
                }
                function get(name){
                    return modules[name];
                }
                return{
                    define: define,
                    get: get
                };
            })();
    
            MyModules.define('bar',[],function(){
                function hello(who){
                    return "Let me instroduce " + who;
                }
                return {
                    hello: hello
                };
            });
            
            MyModules.define("foo",["bar"],function(bar){
                var hungry = "hippo";
                function awesome(){
                    console.log(bar.hello(hungry).toUpperCase());
                }
                return {
                    awesome: awesome
                };
            });
            
            var bar = MyModules.get("bar");
            var foo = MyModules.get("foo");
            console.log(bar.hello("hippo"));    //Let me instroduce hippo
            foo.awesome();      //LET ME INSTRODUCE HIPPO

      ES6中的模块(一个文件,一个模块)

     //bar.js源码
    function hello(who){
        return "Let me instroduce " + who;
    }
    export {hello};
    
     //foo.js源码
    import {hello} from "./bar.js";
    
    let hungry = "hippo";
    function awesome(){
        console.log(hello(hungry).toUpperCase());
    }
    export {awesome};
    
    html.html源码
    <html>
    
    <head></head>
    
    <body>
    
        
    
        <script type="module">
    
           import {awesome} from "./js/foo.js";
           import {hello} from "./js/bar.js";
    
          
           console.log(hello("rhino"));        //Let me instroduce rhino
           awesome();        //LET ME INSTRODUCE HIPPO
    
        </script>
    
    </body>
    
    </html>
  • 相关阅读:
    LeetCode Count of Range Sum
    LeetCode 158. Read N Characters Given Read4 II
    LeetCode 157. Read N Characters Given Read4
    LeetCode 317. Shortest Distance from All Buildings
    LeetCode Smallest Rectangle Enclosing Black Pixels
    LeetCode 315. Count of Smaller Numbers After Self
    LeetCode 332. Reconstruct Itinerary
    LeetCode 310. Minimum Height Trees
    LeetCode 163. Missing Ranges
    LeetCode Verify Preorder Serialization of a Binary Tree
  • 原文地址:https://www.cnblogs.com/zxn-114477/p/14443183.html
Copyright © 2011-2022 走看看