当JavaScript从入门到提高前需要注意的细节:闭包部分


原文链接:点击打开链接


对于希望在javascript技术中提高的人群来说,闭包肯定时常是一个令人感觉神秘的技术。早先有人说javaScript中的闭包可能会引发javaScript内存管理的复杂度,也许会出现内存泄露,所以不建议用闭包。不过jQuery很好的证明了闭包非常好用,C#的Linq也证明的闭包技术的重要性,所以花一点点时间来理解下闭包还是很值得的,再说了,以下的内容不过就是一杯茶的时间而已。

先给出一个闭包的定义:在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。

以上定义中非常重要的是

闭包关联到:函数和变量

闭包锁定了:函数和变量的环境关系


常有人在说闭包前会给出类似以下案例,说是javaScript的特殊性,函数中访问全局变量,这个我一直不太明白,一个函数访问它所在环境中的全局变量很特殊很奇怪吗?

var a = 10;  
function fun1() {  
    alert(a);  
}  
  
  
fun1();  

而且就算有以下代码我也丝毫不感觉有任何问题

var a = 10;  
  
function fun2() {  
    b = 100;// 全局变量  
}  
  
function fun1() {  
    alert(a);  
    alert(b);  
}  
  
fun2();  
fun1();  

真正值得你考量的是以下代码

function fun1(x) {  
    var a = x;  
    function fun2() {  
        return a;  
    }  
    return fun2;  
}  
  
  
alert(fun1(100)()); //100  
alert(fun1(9)()); //9  

如果从结果来看,你也许同样不屑一顾,返回的值很明确的嘛。但是你仔细想想,问题就不简单了

函数fun1的结果是返回了一个fun2的函数。从代码来讲,fun1()是调用了fun1的执行,并且得到了fun2的函数,fun1()()就是说是执行fun2()了!如果你还是感觉正常的话,要么说明你已经理解闭包了,要么就是你忽略了一个重要的事实!

调用fun1()后,fun1所占用的内存应该已经释放了,fun1函数中的所有变量都将释放!!!对不?

function sum(x, y) {  
    var a = x, b = y;  
    return a + b;  
}  
  
  
alert(sum(9, 5));//14  

上面的代码,当我完成sum(9,5)之后,sum函数肯定被释放了,a和b将不存在是不?如果你还是感觉不是很明晰的话,那么看下如下的分解动作吧。

function fun1(x) {  
    var a = x;  
    function fun2() {  
        return a;  
    }  
    return fun2;  
}  
  
  
var fun3 = fun1(10);  
var fun4 = fun1(9);  
alert(fun4()); //9  
alert(fun3()); //10  

看看第一次的fun1将x的值赋值了10,第二次的fun1将x的值赋值为9,而且我们先执行了fun4,要求返还的值是9,再次执行fun3的得到的是10!!!说明什么呢?说明当fun2被创建的时候,它将它所需要用到的变量锁住 了,或者不这么夸张的说是记忆住了。

闭包就是函数在创建自己的时候,将需要用的变量锁住或说记忆住。

这里的函数创建不是指函数声明,而且指函数表达式被激活的时候,匿名函数表达式的激活有:call就是()调用,()分组,还有就是return的时候。

看看如下案例

var dofun = [];  
  
for (var i = 0; i < 10; i++) {  
    dofun[i] = function() {  
        return i;  
    }  
  
}  
  
for (var j = 0; j < 10; j++) {  
    alert(dofun[j]()); //全部返还10  
}  

很多人在网上用过这个案例来说明闭包的特性,我需要很严肃的声明两个问题

  1. 这个案例可以说明闭包
  2. 这个案例还有更神奇的特性说明
dofun[j]()  

的时候才被激活,这个时候i的值是10,所以这个函数被返回了10,要解决这个问题,可以要求函数在i是各种值的时候被激活,怎么激活?return

var dofun = [];  
  
for (var i = 0; i < 10; i++) {  
    dofun[i] = (function(k) {  
        return function() {  
            return k;  
        }  
    }(i));  
  
}  
  
for (var j = 0; j < 10; j++) {  
    alert(dofun[j]()); //全部返还10  
}  

这个处理中很有意思的是,我需要一个k来帮忙,为什么呢?

那就是我刚才说的第2点,先看下如下很令人无语的代码

var dofun = [];  
  
for (var i = 0; i < 10; i++) {  
    dofun[i] = function() {  
        return i;  
    }  
  
}  
  
for (var i = 0; i < 10; i++) {  
    alert(dofun[i]());  
}  

咋一看,你估计会暴跳起来,这不是耍人嘛,结果我们已经知道了,都是10!!!!错!!!!!!弹出的分别是0 1 2 3 4 5 6 7 8 9!!!

不相信你就测试一下看看。你仔细看看代码不同在哪里?下面的for用了变量是i,这就是不同所在,也是闭包的关键所在!

函数是不是值得来锁定一个变量,是看该变量在调用这个函数的时候,是不是能在上下文作用域中找到这个变量,如果无法在调用时找到这个变量,内部函数就会锁住它,否则就不会锁住,至少表面上是这样的。

现在我们再把目光移到最初的那个案例

function fun1(x) {  
    a = x;  
    function fun2() {  
        return a;  
    }  
    return fun2;  
}  
  
  
var fun3 = fun1(10);  
var fun4 = fun1(9);  
alert(fun4()); //9  
a = 999;  
alert(fun3()); //999  

fun3()的结果是999的原因倒不是在乎现在a是全局变量,而是现在fun3在执行的时候能在上下文作用域中找到a了,全局变量不过是凑齐罢了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的体育馆管理系统,源码+数据库+毕业论文+视频演示 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本体育馆管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此体育馆管理系统利用当下成熟完善的SpringBoot框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线选择试题并完成答题,在线查看考核分数。管理员管理收货地址管理、购物车管理、场地管理、场地订单管理、字典管理、赛事管理、赛事收藏管理、赛事评价管理、赛事订单管理、商品管理、商品收藏管理、商品评价管理、商品订单管理、用户管理、管理员管理等功能。体育馆管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 关键词:体育馆管理系统;SpringBoot框架;Mysql;自动化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值