js---11闭包

 //匿名立即调用函数
(function(){//把a,b,f全部隐藏在函数中,外部访问不到,
    var  a = 5;
    var b = 6;
    function f(){
        alert(a);
    }
    window.f  = f;//为了让外部能够访问,把变量a,b隐藏了防止了变量名冲突。保证内成函数使用的变量仅仅是外层函数包括的变量,防止了变量重名。
})();
f();
//自己的scope属性 ==  父级的环境,
//自己的scope属性 == 自己的环境
//闭包:
//函数的嵌套相当于类的继承,函数相当于类,外部函数的变量也是内部函数的,内部函数可以使用,并且变量可以重写(类似于方法的重写)
//作用域链、闭包:函数的嵌套,不是外部类与内部类的关系,是父类与子类的关系,函数是类,内部函数是子类。
//在js层面,只有函数嵌套才会产生闭包。(闭包和全局window对象在浏览器里面都可以查看)。
//闭包的本质是因为js支持作用域链和函数的嵌套。要有函数嵌套才会产生闭包。(词法作用域==静态作用域==闭包)
function f1(){
    var a = 10;
    var b = 20;
    function f2(){//运行在这里的时候就创建了f2的闭包,并且把a,b放在f2的闭包中,所以f2中可以访问a,b.
        console.log(a);//可以访问a,b
    }
    f2();
}
f1();

function f1(){
    var a = 10;
    var b = 20;
    return function f2(){
        console.log(a);
    }
}
var r = f1();
r();//可以访问a,b,由于f2函数(子类)可以访问外部函数(父类)的变量,所以f2函数(子类)运行的时候就会少传递参数(因为可以直接使用父类的成员,包括父级函数的形参)。



function f1(){
    var m = 10;
    function f2(){
        console.log('a');//f2函数没有用到外部函数的变量,不会产生闭包。
    }
    f2();
}
f1();


function f1(){
    var m = 10;
    function f2(){
        var n = 20;
        function f3(){
            console.log(m);//f3不用父级的成员,用父级的父级的成员,会产生闭包
        }
    }
    f2();
}
f1();


----------------------------------------------------------
不用全局变量,使得调用一个函数多次可以使得一个变量累加。
function add(){
    var  a= 0;
    return function(){
        a++;
        ALERT(a)
    };
}
var f = add();
f();f();f();

//使用闭包注意点:
//捕获的父级的变量只是一个引用,不是复制
function f(){//父类
    var num = 1;
    function g(){//子类
        alert(num);
    }
    num++;
    g();//子类对象执行
}
f();//2

//
分析闭包的时候,把函数通过小括号f()执行,不当成c++的函数通过地址调用,当成java的匿名对象执行,分析闭包作用域。
父函数每执行一次产生不同的闭包,函数通过地址调用多次,会产生多个独立的作用域,类似于java多个对象产生 function f(){ var num = 1; return function(){//把子类对象return出去,每return一次都是一个新的对象 num++; alert(num); } } var r1 = f(); r1();//2 r1();//3 var r2 = f();//2个对象 r2();//2 r2();//3 <div id='1'></div> <div id='2'></div> <div id='3'></div> for(var i = 1;i<3;i++){//js没有块作用域,等价于var i ;声明在for的外面,i是一个全局变量, var d = document.getElementById(i); //这里的i已经使用了,所以i对应是0,1,2 d.onclick = function(){ alert(i);//每次都是4,可以通过this,这里i没有使用,一直是i,最后使用的时候i是4了, } } //改写,通过闭包(函数嵌套来解决) for(var i = 1;i<3;i++){ var d = document.getElementById(i); d.onclick = (function(id){ //匿名函数并且立即执行,这里i使用了所以是0,1,2, return function(){ //onclick = 3个不同的子类函数对象,3个子类对象的id值不一样 alert(id); } })(i); //i作为参数传递给id } </script>

    d.onclick函数每执行一次就会产生一个独立的闭包,互不影响,闭包类似于一个对象,互不影响。

分析闭包的时候,把函数通过小括号f()执行,不当成c++的函数通过地址调用,当成java的匿名对象产生了,子函数就是子对象,分析闭包作用域。


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Untitled Document</title>
        <script type=text/javascript charset=utf-8>
        var name = "xiao A";
        var obj = {
              name : "xiao B" ,
              getName: function(){
                return function(){
                    return this.name;
                }
            }
        };
        var k = obj.getName();  //函数结构体return function(){returnthis.name;},这个函数返回后就是全局window的了。
        alert(typeof k); // function类型
        alert(k());//xiao A
        alert(obj.getName()());    //xiao A    ,obj.getName()执行后函数就是window的了,
        
        var name = "xiao A";
        var obj = {
              name : "xiao B" ,
              getName: function(){
                // this总是指向调用者
                var o = this;//this是调用getName的对象
                return function(){
                    return o.name;//o是this,子对象的o永远是父对象的
                }
            }
        };
        alert(obj.getName()());    
        var k = obj.getName();//xiao B
        alert(k());
        
        
        // 闭包:一个函数 可以访问另外一个函数作用域中的变量
        // 封闭性 : private 起到一个保护变量的作用
        // 1 
        function f(x){        // 2 
            var temp = x ;         //局部变量     //temp已经没有被使用    
            return function(x){        // 3 (function 有了一个执行域 var obj)
                temp += x ;        //  又被使用了                        
                alert(temp);                        
             }
        }                
        var a = f(50); //父类只有一个
        alert(a);
        
        a(5);    //子对象1,55            
        a(10);//子对象2,65
        a(20);        //子对象3,85    
        </script>
    </head>
    <body>
    </body>
</html>
原文地址:https://www.cnblogs.com/yaowen/p/6842335.html