• 渡一—— 9-3 闭包-经典版


    //里面有形参,实参,匿名函数,闭包等概念的整理;

    1.原始版

    function createFunctions(){
    	var result = new Array();
    	for(var i=0;i<10;i++){
    		result[i] = function(){ // lv 3
    			return i
    		};
    	}
    	return result;
    }
    var funcs = createFunctions();
    for(var i=0;i<funcs.length;i++){
    	document.write(funcs[i]() + "<br/>");
    }

    //这里执行createFunctions()方法时,会执行完里面的for循环,所以当i退出时i=10;一共调用了10次;
    //output: 10 10 10 10 ...10(10个10)

    2.改进版

    function createFunctions(){
    	var result = new Array();
    	for(var i=0;i<10;i++){
    		result[i] = function(num){ // lv 2 
    			return function(){ // lv 3
    				return num //这里的num是闭包变量,因为他用的是外面function传入的num值,其它地方并没有定义过;
    			}
    		}(i);
    	}
    	return result;
    }
    var funcs = createFunctions();
    for(var i=0;i<funcs.length;i++){
    	document.write(funcs[i]() + "<br/>");
    }
    //output: 0 1 2 3 ...9(0-9)
    

    另一种写法(推荐)

     1 function test(){
     2     var arr = [];
     3     for(var i=0;i<10;i++){
     4         (function(j){
     5             arr[j] = function(){
     6                 console.log(j+"");
     7             }
     8         }(i))
     9     }
    10     return arr;
    11 }
    12 var myArr = test();
    13 for(var j=0;j<10;j++){
    14     myArr[j]();//1 2 3 4 5 ...
    15 }

    2-2.改进版

    function createFunctions(){
        var result = new Array();
        for(var i=0;i<10;i++){
            result[i] = function(i){ // lv 3
                return i
            };
        }
        return result;
    }
    var funcs = createFunctions();
    for(var i=0;i<funcs.length;i++){
        document.write(funcs[i](i) + "<br/>"); 
    }

    //形参是接受参数;实参是传入参数;
    //这里58行(i)是实参;将传入50行的function(i)这里的形参;但如果这里没有形参的话,实参也就没有了意义;
    //但如果实参的个数<形参时,形参中缺少的形参值是undefined;
    //output: 0 1 2 3 ...9(0-9)

    3.总结

    function a() {
    	var i = 0;
    	function b() {
    		alert(++i);
    	}
    	return b;/*注意如果这里没有retrun b;那么调用a()方法时b将不会作为a的一个返回值,这时c=a();c的值就是undefined,也就无法创建闭包;*/
    }
    var c = a();
    c();

    这段代码有两个特点:
    1、函数b嵌套在函数a内部;
    2、函数a返回函数b。
    这样在执行完var c=a()后,变量c实际上是指向了函数b,再执行c()后就会弹出一个窗口显示i的值(第一次为1)。这段代码其实就创建了一个闭包,为什么?因为函数a外的变量c引用了函数a内的函数b,就是说:
    当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。

    简而言之,闭包的作用就是在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量。这是对闭包作用的非常直白的描述,不专业也不严谨,但大概意思就是这样,理解闭包需要循序渐进的过程。
    在上面的例子中,由于闭包的存在使得函数a返回后,a中的i始终存在,这样每次执行c(),i都是自加1后alert出i的值。
    那么我们来想象另一种情况,如果a返回的不是函数b,情况就完全不同了。因为a执行完后,b没有被返回给a的外界,只是被a所引用,而此时a也只会被b引用,因此函数a和b互相引用但又不被外界打扰(被外界引用),函数a和b就会被GC回收。

    闭包的功能:

    /*可以做缓存*/
    function test(){
        var food = "apple";
        var obj = {
            eat:function(){
                if(food != ""){
                    console.log("I am eating" + food);
                    food="";
                }else{
                    console.log("there is nothing!empty!")
                }
            },
            push:function(myFood){
                food = myFood;
            }
        }
        return obj;
    }
    var person = test();
    person.eat();
    person.eat();
    person.push('banana');
    person.eat();
    /*闭包保存变量*/
    function a(){
        function b(){
            var bbb=234;
            console.log(aaa);
        }
        var aaa = 123;
        return b;
    }
    var glob = 100;
    var demo = a();
    demo();
  • 相关阅读:
    Linq基础知识小记四之操作EF
    EF基础知识小记一
    Linq基础知识小记三
    Linq基础知识之延迟执行
    Linq基础知识小记二
    Linq基础知识小记一
    EF 通过DataAnnotations配置属性和类型
    C# 引用类型和值类型
    算法练习之环形链表
    C1128节数超过对象文件格式限制: 请使用 /bigobj 进行编译
  • 原文地址:https://www.cnblogs.com/lisa2544/p/5512913.html
Copyright © 2020-2023  润新知