为了账号安全,请及时绑定邮箱和手机立即绑定

JavaScript设计模式基础之闭包(终)

标签:
JavaScript

对于前端程序员来说闭包还是比较难以理解的,

闭包的形成与变量的作用域以及变量的生产周期密切相关,所以要先弄懂变量的作用域和生存周期。

1.变量作用域

  变量的作用域,就是指变量的有效范围,通常我们指的作用域就是函数作用域(毕竟全局的作用域没有要指的意义,关键哪都能访问)

  声明变量的时候推荐使用es6语法中的let 和const 可以避免var声明变量出现的一些不必要的错误而且let声明变量只作用于当前作用域 避免使用不带var 或者let直接声明变量,可能会导致命名冲突。

2.变量生存周期

  除了变量作用域之外,另外一个跟闭包有关的概念就是变量生存周期。

  对于全局变量来说,它的生存周期就是永久,除非我们主动销毁它,而对于函数里面声明的变量来说 它的生存周期会随着函数调用解释而被销毁。

闭包的定义: 最简单直白的说法就是 函数返回函数

闭包的应用:封装私有变量、延续局部变量的寿命

1.封装私有变量:

  使用闭包可以把一些不需要暴露在全局的变量封装成“私有变量”

  如有一个计算数组偶数乘积的方法:

复制代码

    let num = function(arr){         let a = 1;         for(let i = 0; i < arr.length; i++){             if(arr[i] % 2 === 0){                 a *= arr[i];             }         }         return a;     }         console.log( num([1,2,3,4]));//输出8

复制代码

加入缓存机制提高函数性能:

复制代码

let cache = {};     let num = function(arr){         let args = Array.prototype.join.call(arr,',');//输出1,2,3,4         console.log(cache[args])//第一次调用输出为undefined进行下一步计算 第二次调用输出8 直接返回         //传入相同参数就比不必进行计算 直接返回缓存提高性能         if(cache[args]){             return cache[args];         }         //不是相同参数则进行计算         let a = 1;         for(let i = 0; i < arr.length; i++){             if(arr[i] % 2 === 0){                 a *= arr[i];             }         }         return cache[args] = a;     }         console.log( num([1,2,3,4]));//8 进行计算     console.log( num([1,2,3,4]));//8 返回缓存

复制代码

这明显能看到cache这个缓存变量只在num函数里面被使用,与其让它们一起暴露在全局不然把它封装在num函数内部,减少页面中的全局变量,以免该变量在其他地方被修改而引发错误

封装后代码如下:

  

复制代码

let num = (function(){         let cache = {};         return function(arr){             let args = Array.prototype.join.call(arr,',');//输出1,2,3,4             console.log(cache[args])//第一次调用输出为undefined进行下一步计算 第二次调用输出8 直接返回             //传入相同参数就比不必进行计算 直接返回缓存提高性能             //判断cache缓存对象里面有args这个key值没             if(args in cache){                 return cache[args];             }             //不是相同参数则进行计算             let a = 1;             for(let i = 0; i < arr.length; i++){                 if(arr[i] % 2 === 0){                     a *= arr[i];                 }             }             return cache[args] = a;         }             })();         console.log( num([1,2,3,4]));//8 进行计算     console.log( num([1,2,3,4]));//8 返回缓存

复制代码

2.延续局部变量寿命

src属性会自动请求服务器数据如下

复制代码

  let report = function(src){             let img = new Image();             img.src = src;             console.log(img.src);         }         report(`https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1537779456907&di=c72dd79d1dbb02bb9340743bf08e99f7&imgtype=0&src=http%3A%2F%2Fe.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F94cad1c8a786c91723e93522c43d70cf3ac757c6.jpg`);

复制代码

 

  但是一些低版本的浏览器实现存在着bug,在这些浏览器上面使用该函数会丢失数据 因为函数调用结束后变量销毁 我们可以用闭包封闭起来就能解决低版本浏览器bug

代码如下:

复制代码

  let report = (function(){             let imgs = [];             return function(src){                 let img = new Image();                 imgs.push(img);                 img.src = src;             }                      })()         report(`https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1537779456907&di=c72dd79d1dbb02bb9340743bf08e99f7&imgtype=0&src=http%3A%2F%2Fe.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F94cad1c8a786c91723e93522c43d70cf3ac757c6.jpg`);

复制代码

 

接下来要来点干货了 

用闭包实现命令模式:

在JavaScript中闭包的各种设计模式实现里面,闭包的运用特别广泛,在我后续的博客中将体会到这一点

简单编写一段闭包实现命令模式 如果上述的闭包使用你基本会了的话不会对我们的理解造成困难

代码如下:

复制代码

<!DOCTYPE html> <html> <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <meta http-equiv="X-UA-Compatible" content="ie=edge">     <title>Document</title> </head> <body>     <button id="start">打开电脑</button>     <button id="end">关闭电脑</button>     <script>         //命令         let Computer = {             open(){                 alert('打开电脑');             },             close(){                 alert('关闭电脑');             }         }         //创建命令执行中介         let createCommand = function(receiver){             //执行             let execute = function(){                 return receiver.open();             }             //关闭             let undo = function(){                 return receiver.close();             }             return {                 execute,                 undo             }         };         //设置执行命令者         let setCommand = function(command){             document.querySelector('#start'). = function(){                 command.execute();//输出打开电脑             }             document.querySelector('#end'). = function(){                 command.undo();//输出关闭电脑             }         }         //传入命令方法 传入执行中介      setCommand(createCommand(Computer));     </script> </body> </html>

复制代码

代码还是不难重在理解 

  

原文出处:https://www.cnblogs.com/y-y-y-y/p/9695498.html  

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 1
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消