理解js中的闭包

闭包 我的理解是 能够有权访问另一个函数作用域中变量的函数

 

通常我们知道 普通的函数在调用完成之后,活动对象不会从内存中销毁,其执行环境的作用域链会被销毁,造成资源的浪费 而闭包的好处就在于执行完就会被回收 不会造成资源的极大的浪费 性能也会相应的提升~

闭包的几种写法

 1 //当只有一个返回的内部函数时候
 2 
 3 //第一种写法
 4 function test1(a,b){
 5 
 6     return function(c){
 7           console.log(a + b + c);
 8       }
 9 
10   }
11   var m1 = test1(2,4);
12   m1(5);
13 
14 //输出 11
15 
16 
17 //第二种写法
18 
19 function test2(a,b){
20         var name = 'xsdsfsfsdxcxcx';
21 
22       function xx(c){
23             console.log(a + b + c);
24         }
25       return xx;
26     }
27     var m2 = test2(2,4);
28     m2(5);
29 
30 //输出 11

若有多个需要返回的内部函数 可使用对象的方法一一列举出来 又称模块模式

 1 // 多个返回的内部函数
 2   function test2(a,b){
 3       var name = 'xsdsfsfsdxcxcx';
 4 
 5     function xx(c){
 6           console.log(a + b + c);
 7     }
 8     function ss(){
 9       // js中replace默认只替换查找到的第一个值 若要替换多个值需要使用正则
10       var _replace = name.replace('x','aa');
11       console.log(_replace);
12     }
13     function allReplace(){
14       var re = /x/g;
15       var _replace = name.replace(re,'X');
16       console.log(_replace);
17     }
18     return {
19       xx : xx,
20       ss : ss,
21       allReplace: allReplace
22     }
23   }
24   var m2 = test2(2,4);
25   m2.ss();     //输出  aasdsfsfsdxcxcx
26   m2.xx(3);    //输出  9
27   m2.allReplace(); //输出 XsdsfsfsdXcXcX

 

简单的案例看下 静态方法和实例方法的区别

 1  1 var test1 = function(){
 2  2 
 3  3 }
 4  4 test1.Show = function(){
 5  5     alert('静态方法!');
 6  6 }
 7  7 test1.prototype.Display = function(){
 8  8     alert('实例方法!');
 9  9 }
10 10 
11 11 test1.Show();                       //静态方法   只能直接用类名进行调用 不能使用this
12                        //函数才有prototype属性 对象是没有的
13 
14 12 test1.Display();                    //报错  这是一个是实例方法 必须先实例化后才能进行调用
15 13 
16 14 
17 15 var Demo = new test1();
18 16 Demo.Display();                    //实例方法

再来看一段代码

 1 var dom = function(){
 2         var Name = "Default";
 3         this.Sex = "Boy";
 4         this.success = function(){
 5             alert("Success");
 6         };
 7 };
 8  
 9 alert(dom.Name);      //undefined         这是因为每个function都会形成一个作用域 而这些变量声明在函数中 所以就处于这个函数的作用域中 外部是无法访问的 必须new一个实例
10 alert(dom.Sex);       //undefined

再来一段代码

 1 var html = {
 2         Name:'Object',
 3         Success:function(){
 4             this.Say = function(){
 5                     alert("Hello,world");
 6             };
 7             alert("Obj Success");
 8         }
 9 };
10 //html是一个对象,不是函数,所以没有Prototype属性,其方法也都是公有方法,html不能被实例化。
11 //我们可以这样使用它 html.Name 和 html.Success()
12 //当然我们也可以将这个对象作为一个值赋给其他变量 比如 var a = html

那么问题来了 我们该如何访问Success方法中的Say方法呢 难道是html.Success.Say()吗? 当然这样式错误的啦  因为在Say方法中又开始了一个新的function形成新的作用域 肯定是访问不到里面的内容啦 

得做点修改 比如

 1  1 var s = new html.Success(); 
 2  2 s.Say();        //Hello,world
 3  3 
 4  4 
 5  5 //或者写在外面
 6  6 html.Success.prototype.Show = function(){
 7  7     alert("HaHa");
 8  8 };
 9  9 var s = new html.Success();
10 10 s.Show();
11  

 

说了这么多 那么闭包的用途到底是什么呢?

事实上通过使用闭包 我们可以做很多事情 比如模拟面向对象的代码风格 更优雅 更简洁的表达出代码 这是一个有点追求美感的程序员应该做的 而且在某些方面可以提升代码的执行效率

 1 匿名自执行函数

 1 var data  = {
 2        arr : [2,5,2,4,333],
 3        tree : {}
 4   }
 5   (function(x){
 6     var row,
 7         new_arr = [];
 8       for(var i = 0; i < x.arr.length; i ++){
 9         row = x.arr[i];
10         new_arr.push(row);
11       }
12       return new_arr;
13   })(data)   //输出 [2,5,2,4,333]

创建了一个匿名函数 并立即执行 由于外部无法直接访问内部的变量 因此在函数执行完成后会立刻释放资源 还不会污染全局变量

 

2 缓存作用

将计算结果缓存在内部 之后再调用的话就可以直接使用

 

3 封装

 1 var package  = function(){
 2       var name = '张三';
 3 
 4       return {
 5           getName : function(){
 6               return name;
 7           },
 8           setName : function(names){
 9               name = names;
10               return name;
11           }
12       }
13 }();
14 
15 package.getName();         //张三
16 package.setName('李四');  // 李四
17 
18 package.name;                //undefined

 

4 类和继承

 

 1 function Mother(){
 2   var eye = 'default';
 3 
 4   return {
 5     getName : function(){
 6       return eye;
 7     },
 8     setName :  function(newName){
 9       name = newName;
10       return name;
11     }
12   }
13 }
14 
15 var M = new Mother();
16 M.getName();
17 M.setName('beautiful!');
18 
19 var Person = function(){
20 
21 }
22 //继承
23 Person.prototype = M;
24 Person.prototype.Say = function(){
25   console.log('这是私有方法!');
26 }
27 var p = new Person();
28 p.getName();    
29 p.setName('hah');
30 p.Say();                                

 

posted on 2016-10-31 21:41  Seapard  阅读(114)  评论(0编辑  收藏  举报

导航