理解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();                                

 

转载于:https://www.cnblogs.com/Seapard/p/6017463.html

内容概要:本文深入探讨了Kotlin语言在函数式编程和跨平台开发方面的特性和优势,结合详细的代码案例,展示了Kotlin的核心技巧和应用场景。文章首先介绍了高阶函数和Lambda表达式的使用,解释了它们如何简化集合操作和回调函数处理。接着,详细讲解了Kotlin Multiplatform(KMP)的实现方式,包括共享模块的创建和平台特定模块的配置,展示了如何通过共享业务逻辑代码提高开发效率。最后,文章总结了Kotlin在Android开发、跨平台移动开发、后端开发和Web开发中的应用场景,并展望了其未来发展趋势,指出Kotlin将继续在函数式编程和跨平台开发领域不断完善和发展。; 适合人群:对函数式编程和跨平台开发感兴趣的开发者,尤其是有一定编程基础的Kotlin初学者和中级开发者。; 使用场景及目标:①理解Kotlin中高阶函数和Lambda表达式的使用方法及其在实际开发中的应用场景;②掌握Kotlin Multiplatform的实现方式,能够在多个平台上共享业务逻辑代码,提高开发效率;③了解Kotlin在不同开发领域的应用场景,为选择合适的技术栈提供参考。; 其他说明:本文不仅提供了理论知识,还结合了大量代码案例,帮助读者更好地理解和实践Kotlin的函数式编程特性和跨平台开发能力。建议读者在学习过程中动手实践代码案例,以加深理解和掌握。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值