摘要:前言之前发了一篇文章,写了一些对于闭包的理解。现在补上闭包的应用篇,很惭愧因为严重的拖延症一直拖到现在。本文主要分享一些常见的闭包用法和分析,也希望能增加对闭包的理解。
前言
之前发了一篇文章,写了一些对于闭包的理解。现在补上闭包的应用篇,(很惭愧因为严重的拖延症一直拖到现在)。本文主要分享一些常见的闭包用法和分析,也希望能增加对闭包的理解。
简单回顾在之前的文章里,讲解了闭包的原理,如果忘记了可以点击这里再看一下,在这里我们简单回顾一些知识点:
闭包的本质是一个函数
闭包可以访问函数内部变量
闭包的存在会使内部变量保留在内存中
闭包的应用闭包常见的用法,就将围绕这些特点展开:
1.模仿块级作用域首先简单举个例子来,解释一下什么是块级作用域:
function A(num) { for (var i = 0; i < num; i++) { num++; } console.log(i) }
在这个简单的函数中,变量i是在for循环中定义的,如果是在C++或者Java中,这样定义的变量,一旦循环结束,变量也就随之销毁,i的作用范围只在循环这个小块,就称为块级作用域。在javascript中,没有这样的块级作用域,前面一篇文章已经提到,变量是定义在函数的活动对象中的,因此,从定义i开始,在函数内部可以随时访问它。
这样的坏处显而易见:由于javascript不会告诉你变量是否已经被声明,容易造成命名冲突,如果是在全局环境定义的变量,就会污染全局环境,因此可以利用闭包特性来模拟块级作用域。不过在此之前要先介绍另一个知识点:匿名立即执行函数。如果已经比较熟悉的同学可以直接跳过这一块:
首先举个例子(我比较喜欢举例,感觉看例子比较更容易理解):
var helloWorld = function(){ alert("Hello world") } helloWorld();//执行函数
上面的简短代码一共就做两件事:1.定义了一个匿名函数并赋值给helloWorld;2.在helloWorld后面加括号表示调用函数,所以 匿名函数如果直接执行,是不是应该这样写:
function(){ alert("Hello world") }()
这样的写法会报错,因为在javascript中,function是函数声明的标志,不允许在后面直接加括号,而应该写成这样:
(function(){ //函数体 alert("Hello world") })()
也就是把声明部分加括号即可,加了括号以后,这一段代码就相当于执行了里面的函数体部分,但是此时内部的变量已经不能被外部访问,请看下面详细样例
具体实现现在我们讲模拟块级作用域的具体步骤,假设还是针对前面的A函数,如果我们想让i变量只有块级作用域,可以这样写:
function A(num) { //核心代码 (funnction(){ for(var i = 0; i注意看核心代码部分,我们用刚刚讲到的匿名自执行函数在内部形成了一个闭包,这个闭包在哪呢?一直强调,闭包的本质是函数,其实在这里闭包就是那个匿名函数,这个闭包可以到函数A内部的活动变量,又能保证自己内部的变量在自执行后直接销毁,这个应该不难理解了
优点分析这种写法的经常用在全局环境中,可以避免添加太多的全局变量和全局函数,特别是多人合作开发的时候,可以减少因此产生的命名冲突等,避免污染全局环境。
2.存储变量我们知道闭包的另一个特点是可以保存外部函数的变量,原理是基于javascript中函数作用域链的特点,内部函数保留了对外部函数的活动变量的引用,所以变量不会被释放(这一块没有理解清楚的请看前一篇文章,里面讲的比较详细),然后我们再来愉快地举例子:
function B(){ var x = 100; return { function(){ return x } } } var m = B()//运行B函数,生成活动变量 x被m引用这是前文介绍过的一个最简单的闭包例子,我们运行B函数,返回值就是B内部的匿名函数,此时m引用了变量x,所以B执行后x不会被释放,利用这一点,我们可以把比较重要或者计算耗费很大的值存在x中,只需要第一次计算赋值后,就可以通过m函数引用x的值,不必重复计算,同时也不容易被修改
优点分析这种写法可能会用在把一些不经常变动,但是计算比较复杂的值保存起来,就可以节省每次访问的时间。
3.封装私有变量javascript中没有私有成员的概念,我们可以把函数当做一个范围,函数内的变量就是私有变量,在外部无法引用,比如:
function C(a,b){ var c = a - b ; return c }在这个函数中,a b c都是私有变量,在外部无法访,利用闭包的特点,我们可以就可以创建可以访问私有变量的方法:
function Person(){ var name = "default"; this.getName:function(){ return name; } this,setName:function(value){ name = value; } } console.log(Person.getName())//default console.log(Person.setName("mike")) console.log(Person.getName())//mike在这个例子中,设置了两个闭包函数来操作Person函数内部的name变量,除了这两个函数,在外部无法再访问到name变量,name也就相当于是私有成员。在这个例子中,我们用的是在构造函数中定义公有方法,对于所有的Person实例,都分别创建了新的办法,当然还可以使用其他形式来避免这个问题,要涉及到创建对象模式的一些知识,在这里说明怕反而增加了闭包的理解难度,之后在写对象和继承的时候再提到(下一次更新一定不会这样久了QAQ)。
小结关于闭包的主要主要应用就讲到这里,本文中很多知识点与上一篇文章有关,又因为发布相隔时间比较长(我的锅),建议大家可以先看看上一篇复习一下,这篇相对来前一篇容易理解,而且在举例过程尽量没有加入其它的疑难知识点,希望能对看到的人有所帮助。以上内容属于个人见解,如果有不同意见,欢迎指出和探讨。同时,码字不易请尊重作者的版权,转载请注明出处,如作商用,请与作者联系,感谢!
补充如果看完对您有帮助,顺手点个推荐呗~
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/86962.html
摘要:闭包的学术定义先来参考下各大权威对闭包的学术定义百科闭包,又称词法闭包或函数闭包,是引用了自由变量的函数。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。 前言 上一章讲解了闭包的底层实现细节,我想大家对闭包的概念应该也有了个大概印象,但是真要用简短的几句话来说清楚,这还真不是件容易的事。这里我们就来总结提炼下闭包的概念,以应付那些非专人士的心血来潮。 闭包的学术...
摘要:引言满满的干货,面试必系列,参考大量资料,并集合自己的理解以及相关的面试题,对核心知识点中的作用域闭包上下文进行了梳理。本篇重点介绍闭包和。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。 showImg(https://segmentfault.com/img/bVbo4hv?w=1800&h=1000); 引言 满满的干货,面试必bei系列,参考大量资料,并集...
摘要:一般来讲,函数执行完毕后,局部活动对象就会被销毁,内存中仅保存全局作用域,但是闭包的情况有所不同理解闭包的前提先理解另外两个内容作用域链垃圾回收作用域链当代码在执行过程中,会创建变量对象的一个作用域链。 闭包是javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包来实现。个人的理解是:函数中嵌套函数。 闭包的定义及其优缺点 闭包是指有权访问另一个函数作用域中的变量的...
阅读 3384·2019-08-30 10:54
阅读 3119·2019-08-29 16:38
阅读 2082·2019-08-26 14:06
阅读 1462·2019-08-23 15:39
阅读 2998·2019-08-23 15:37
阅读 2860·2019-08-23 13:50
阅读 3136·2019-08-22 17:14
阅读 2316·2019-08-22 15:44