看到标题“闭包”很多人会觉得懵逼包括我在内,之前对闭包有所听闻但始终无法准确全面的了解。对于前端同学无论在面试还是在开发,都逃不过关于闭包的问题。最近小程序项目中遇到变量访问权限的问题一时间没考虑到闭包,郁闷了,在此感谢@Topqiang给我指点。本文阅读一遍不一定能够理解掌握,需要反复推敲和练习,有疑问欢迎随时在下方评论。
在网上搜索学习关于闭包的技术时发现讲的都比较抽象【我是菜鸟】,不好理解闭包的概念以及使用方法。今天我们带着疑问去学习:首先我给大家还原一下需求场景;对需求场景进行分析;引入闭包解决方案;升华闭包概念理解。废话少说直接步入正题。
还原需求场景
我要实现一个未知的多对多的数据请求并加载到页面中,由于后端接口限制,不支持多对多的同步返回,需要前端去做数据匹配处理。
下面来看看这种需求场景下,小程序前端代码是什么样子
按照常规双层for循环逻辑来理解是没有问题的,内层访问外层变量去遍历list
需求场景分析
这种需求下有同学会考虑后台将双层数据处理后返回给前端,但是如果后端考虑业务功能的解耦不做此操作,我们还是要解决这个问题。亲测单纯的双层for循环中内层访问外层变量是Ok的,加入wx.request过后内层将无法正常访问外层循环变量 i 。如果外层数据res.data的长度为3,那么i在外层for循环中正常遍历为:0、1、2;但是在内层for循环中遍历 i 的数据为:3、3、3,这个时候我对showdata.data赋值无法拿到完整的数据,而只能拿到最后一遍遍历出的数据。
分析到这里我们的目的就明确了,要想在内层wx.request中的for循环中得到外层变量 i ,怎么实现呢?
闭包解决方案
JS闭包可以很轻松的解决内层访问外层存活的私有变量。下面给出3种解决方案,仅供参考。
方案一:增加若干个对应的闭包域空间(这里采用的是匿名函数),专门用来存储原先需要引用的内容(下标),不过只限于基本类型(基本类型值传递,对象类型引用传递)
方案二:增加若干个对应的闭包域空间用来存储下标,将事件绑定在新增的匿名函数返回的函数上
方案三:使用ES6新语法 let 关键字:块作用域,不能重复声明覆盖,限制了变量的作用域,保证变量不会去污染全局变量
网上针对javascript解决闭包的方案还有很多,有兴趣的朋友可以深入了解。看了这么多内容不知道大家是否对微信小程序闭包有所了解。网上针对微信小程序闭包代码搜索最多的是下图:
升华闭包概念
闭包到底是什么?
官方的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分,闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。
了解JS闭包之前我们回忆一下变量的作用域。javascript特殊的作用域函数内部变量访问全局变量,函数外部无法获取函数内的局部变量。函数内部声明变量要用var,不用var则声明全局变量。
Javascript语言的“链式作用域”结构(chain scope)导致子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的。闭包也就是将函数内部和函数外部连接起来的中介。
作用和应用场景
闭包可以读取函数内部的变量,也可以让这些变量的值始终保持在内存中。
在内存中维持一个变量。
通过保护变量的安全实现JS私有属性和私有方法(不能被外部访问)私有属性和方法在Constructor外是无法被访问的【本文涉及的场景】
闭包的注意点