//匿名立即调用函数 (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>