经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JavaScript » 查看文章
理解js闭包9大使用场景
来源:cnblogs  作者:林恒  时间:2020/12/28 9:51:16  对本文有异议

1.返回值(最常用)

  1. //1.返回值 最常用的
  2. function fn(){
  3. var name="hello";
  4. return function(){
  5. return name;
  6. }
  7. }
  8. var fnc = fn();
  9. console.log(fnc())//hello

这个很好理解就是以闭包的形式将 name 返回。

2.函数赋值

  1. var fn2;
  2. function fn(){
  3. var name="hello";
  4. //将函数赋值给fn2
  5. fn2 = function(){
  6. return name;
  7. }
  8. }
  9. fn()//要先执行进行赋值,
  10. console.log(fn2())//执行输出fn2

在闭包里面给fn2函数设置值,闭包的形式把name属性记忆下来,执行会输出 hello。

3.函数参数

  1. function fn(){
  2. var name="hello";
  3. return function callback(){
  4. return name;
  5. }
  6. }
  7. var fn1 = fn()//执行函数将返回值(callback函数)赋值给fn1,
  8. function fn2(f){
  9. //将函数作为参数传入
  10. console.log(f());//执行函数,并输出
  11. }
  12. fn2(fn1)//执行输出fn2

用闭包返回一个函数,把此函数作为另一个函数的参数,在另一个函数里面执行这个函数,最终输出 hello

4.IIFE(自执行函数)

  1. (function(){
  2. var name="hello";
  3. var fn1= function(){
  4. return name;
  5. }
  6. //直接在自执行函数里面调用fn2,将fn1作为参数传入
  7. fn2(fn1);
  8. })()
  9. function fn2(f){
  10. //将函数作为参数传入
  11. console.log(f());//执行函数,并输出
  12. }

直接在自执行函数里面将封装的函数fn1传给fn2,作为参数调用同样可以获得结果 hello

5.循环赋值

  1. //每秒执行1次,分别输出1-10
  2. for(var i=1;i<=10;i++){
  3. (function(j){
  4. //j来接收
  5. setTimeout(function(){
  6. console.log(j);
  7. },j*1000);
  8. })(i)//i作为实参传入
  9. }

如果不采用闭包的话,会有不一样的情况,可以看我自己 闭包 的文章。

6.getter和setter

  1. function fn(){
  2. var name='hello'
  3. setName=function(n){
  4. name = n;
  5. }
  6. getName=function(){
  7. return name;
  8. }
  9. //将setName,getName作为对象的属性返回
  10. return {
  11. setName:setName,
  12. getName:getName
  13. }
  14. }
  15. var fn1 = fn();//返回对象,属性setName和getName是两个函数
  16. console.log(fn1.getName());//getter
  17. fn1.setName('world');//setter修改闭包里面的name
  18. console.log(fn1.getName());//getter

第一次输出 hello 用setter以后再输出 world ,这样做可以封装成公共方法,防止不想暴露的属性和函数暴露在外部。

7.迭代器(执行一次函数往下取一个值)

  1. var arr =['aa','bb','cc'];
  2. function incre(arr){
  3. var i=0;
  4. return function(){
  5. //这个函数每次被执行都返回数组arr中 i下标对应的元素
  6. return arr[i++] || '数组值已经遍历完';
  7. }
  8. }
  9. var next = incre(arr);
  10. console.log(next());//aa
  11. console.log(next());//bb
  12. console.log(next());//cc
  13. console.log(next());//数组值已经遍历完

8.首次区分(相同的参数,函数不会重复执行)

  1. var fn = (function(){
  2. var arr=[];//用来缓存的数组
  3. return function(val){
  4. if(arr.indexOf(val)==-1){//缓存中没有则表示需要执行
  5. arr.push(val);//将参数push到缓存数组中
  6. console.log('函数被执行了',arr);
  7. //这里写想要执行的函数
  8. }else{
  9. console.log('此次函数不需要执行');
  10. }
  11. console.log('函数调用完打印一下,方便查看已缓存的数组:',arr);
  12. }
  13. })();
  14. fn(10);
  15. fn(10);
  16. fn(1000);
  17. fn(200);
  18. fn(1000);

执行结果如下:

可以明显的看到首次执行的会被存起来,再次执行直接取。

9.缓存

  1. //比如求和操作,如果没有缓存,每次调用都要重复计算,采用缓存已经执行过的去查找,查找到了就直接返回,不需要重新计算
  2. var fn=(function(){
  3. var cache={};//缓存对象
  4. var calc=function(arr){//计算函数
  5. var sum=0;
  6. //求和
  7. for(var i=0;i<arr.length;i++){
  8. sum+=arr[i];
  9. }
  10. return sum;
  11. }
  12. return function(){
  13. var args = Array.prototype.slice.call(arguments,0);//arguments转换成数组
  14. var key=args.join(",");//将args用逗号连接成字符串
  15. var result , tSum = cache[key];
  16. if(tSum){//如果缓存有
  17. console.log('从缓存中取:',cache)//打印方便查看
  18. result = tSum;
  19. }else{
  20. //重新计算,并存入缓存同时赋值给result
  21. result = cache[key]=calc(args);
  22. console.log('存入缓存:',cache)//打印方便查看
  23. }
  24. return result;
  25. }
  26. })();
  27. fn(1,2,3,4,5);
  28. fn(1,2,3,4,5);
  29. fn(1,2,3,4,5,6);
  30. fn(1,2,3,4,5,8);
  31. fn(1,2,3,4,5,6);

输出结果:

 

转载于:https://blog.csdn.net/dkm123456/article/details/111644638

原文链接:http://www.cnblogs.com/smileZAZ/p/14189126.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号