JS闭包的基础知识,闭包的本质,闭包的作用,闭包的间谍属性和闭包的遗憾
JS闭包总结来源和扩展知识来自于:
1.简书:彻底搞懂JS闭包各种坑
2.百度百科 闭包
闭包不是JS独有的特性。但本文以JS闭包来了解闭包的。
1.闭包的本质:是一个函数。
2.闭包的作用:间谍作用,延长变量生命周期。
3.闭包的构成模型:A函数,内部有一个间谍B函数,B函数能访问A函数的私有变量,并返回给A函数外部一些数据。这里的B函数,就叫做闭包。
4应用场景
1、保护函数内的变量安全。以最开始的例子为例,函数a中i只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。
2、在内存中维持一个变量。依然如前例,由于闭包,函数a中i的一直存在于内存中,因此每次执行c(),都会给i自加1。
以上两点是闭包最基本的应用场景,很多经典案例都源于此。
5.回收机制
参数和变量不会被垃圾回收机制回收
在Javascript中,如果一个对象不再被引用(注意这里写的不是调用,调用和引用是两回事。调用是运行,引用是引用地址),那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。
function a(){
var x=1
return function b(){
var y=1
console.log(x++) //间谍闭包,拉拢了外部的变量x,使用后++,返回原值再增加
console.log(y++) //间谍闭包,使用了内部了变量y,使用后++,返回原值再增加
}
}
//console.log(x), 这时候会报错,外部无法直接访问x。使用闭包,就可以间接的访问x了。
//a(),直接运行a,会返回,return之后的,闭包函数代码 function b(){....}
//b(),直接使用闭包,也会报错,因为无法直接使用闭包,必须使用a才能访问b
//所以,b是一个技术很水的间谍,无法跟外部直接沟通。所以b叫做外交部长,更合适点吧。
var c=a() //创建一个全部变量C,来引用b,只有通过运行a()才能调用b函数。
//可以使用a()().这里为了方便使用c代替a()
c() //这里执行了闭包函数b,结果为1 1,这里a中的x被修改成了2。
setTimeout(c(),5000)
// 延迟5秒,再执行一次,看看如何,发现x依然在内存中,y不在内存中,结果 2 1
c() //这里再次执行了闭包函数。也就是return后面的函数。执行结果3 1
//a和b一直存在内存中的原因:C是全局变量,生命周期很长。C引用a()的地址,所以a()执行一次,计算结果是b所以b也一直在内存中。
//x在内存,y不在内存的原因:间谍函数b的小算盘:x在b的外部,不牵制住,就会丢掉。y在b的内部,可以随时创建
6.使用注意点
(1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
(2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
暂时先总结到这里吧。还有一些,也会在本文继续修改更新