JavaScript 的闭包原理与详解。

JavaScript 的闭包原理与详解。
JavaScript的闭包是一个特色,但也是很多新手难以理解的地方,阅读过不少大作,对闭包讲解不一,个人以为,在《JavaScript高级程序设计》一书中,解释的最为详尽,结合此书,表述一下我对JavaScript闭包的理解,希望能对新手有些帮助。

闭包的例子

var count=10;//全局作用域 标记为flag1
function add(){
    var count=0;//函数全局作用域 标记为flag2
    return function(){
        count+=1;//函数的内部作用域
        alert(count);
    }
}
var s=add()
s();//输出1
s();//输出2

来看一下发生了什么吧,add()的返回值是一个函数,首先第一次调用s()的时候,是执行add()的返回的函数,也就是下面这个函数:

function(){
        count+=1;//函数的内部作用域
        alert(count);
    }

也就是将count+1,在输出,那count是从哪儿来的的呢,根据作用域链的规则,底层作用域没有声明的变量,会向上一级找,找到就返回,没找到就一直找,直到window的变量,没有就返回undefined。这里明显count 是函数内部的flag2 的那个count ,

var count=10;//全局作用域
function add(){
    //var count=0;注释掉了
    return function(){
        count+=1;//函数的内部作用域
        alert(count);
    }
}
var s=add()
s();//输出11
s();//输出12

自然这是体现不出闭包的性质,只为了说明函数作用域链
继续说明:第一次执行,是没有疑问的输出1,那第二次的过程是怎样的呢?
继续执行那个函数的返回的方法,还是count+=1;然后再输出count ,这里问题就来了,不应该继续向上寻找,找到count=0;然后输出1吗?不知道有没有注意一个问题,那就是s()执行的是下面这个函数

function(){
        count+=1;//函数的内部作用域
        alert(count);
    }

而不是

function add(){
    var count=0;//函数全局作用域 标记为flag2
    return function(){
        count+=1;//函数的内部作用域
        alert(count);
    }
}

也就是说add(),只被执行了一次。然后执行两次s(),那count的值就是只声明了一次。

var s=add(),函数add 只在这里执行了一次。

下面执行的都是s(),那第二次的count的值是从哪儿来的,没错它还是第一次执行add时,留下来的那个变量。

(这怎么可能,函数变量执行完就会被释放啊,为什么还在?这里就是一个垃圾回收机制的引用计数问题)。

“”如果一个变量的引用不为0,那么他不会被垃圾回收机制回收,引用,就是被调用“”。

由于再次执行s()的时候,再次引用了第一次add()产生的变量count ,所以count没有被释放,第一次s(),count 的值为1,第二次执行s(),count的值再加1,自然就是2了。

让我们返回来再看看,根据以上所说,如果执行两次add() ,那就应该输出 都是1,来改一下这个函数

function add(){
    var count=0;//函数全局作用域
    return function(){
        count+=1;//函数的内部作用域
        alert(count);
    }
}
add()();//输出1
add()();//输出1

哈哈~果真如此。输出的两次都是1. 不知道通过这个示例,你有没有理解了闭包。 描述一下闭包的结构吧,为什么闭包一般都需要一个匿名函数,为了实现作用域链的规则,需要有两层作用域。 想来大家都应该理解了。 下面再描述一个常见的错误

<p>1</p><p>2</p><p>3</p>
<p>4</p><p>5</p><p>6</p>

var plist=document.getElementsByTagName('p');
for (var i=0;i<plist.length;i++) {
    plist[i].onclick=function(){
        alert(plist[i].innerHTML)//全是undefined
    }
}

想要点击相应的p 弹出对应的i的值,但是这里发生了什么,点击任意一个数,弹出的都是undefined,我的天,不应该是1,2,3,4,5,6的吗? 解释一下,函数执行完,i 的值是6 ,没有错吧。那plist[6]是不是undefined。 我们点击的时候,触发的就是输出undefined,(づ。◕‿‿◕。)づ,但我们想要的值是点击对应的p 的innerHTML, alert(this.innerHTML)//万事大吉, this 是一个好东西,指向当前对象当我们绑定的时候绑定的就是当前值,而不是动态的i的值,前面绑定的是一个动态i 的值,这里也可以使用闭包解决,不过不推荐,毕竟闭包使用的话,会让内存无法释放,也就是闭包越多,占的内存越多。使用需谨慎。

总结一下

JavaScript闭包的形成原理是基于函数变量作用域链的规则 和 垃圾回收机制的引用计数规则。
JavaScript闭包的本质是内存泄漏,指定内存不释放。
(不过根据内存泄漏的定义是无法使用,无法回收来说,这不是内存泄漏,由于只是无法回收,但是可以使用,为了使用,不让系统回收)
JavaScript闭包的用处,私有变量,获取对应值等,。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值