闭包
变量的作用链
- JS变量有两种:全局变量、局部变量
- 局部变量作用域一般在函数里,在函数外的视为全局变量
- 在函数里面可以访问全局的变量,在函数外面不可以访问到函数里面的变量
- JS存在“链式作用域”结构,可以理解为函数嵌套,子对象会一级一级的向上寻找父对象的变量。所以,父对象的所有变量对子对象都是可见的。
var str1="hello";//全局变量
function fun(){
var res="i am coming";//fun()内的局部变量
}
function funa(){
var str2=" world";//funa()内的局部变量
function funb(){
function func(){
console.log(str1);//hello
console.log(str2);//world
console.log(res);//报错,undefined
}
func();
}
funb();
}
funa();
console.log(str2);//报错
function fun1() {
var a = 0;
console.log(a);
return function () {
a++;
console.log(a);
}
}
//注意这种调用的结果:
var res = fun1();
res();
res();
res();
-
第一次执行var res = fun1()把匿名函数的引用传给了变量res
-
每次执行res()即在调用匿名函数
- 一般来说局部变量在函数执行之后就会被垃圾回收机制回收,但是调用res()之后变量a没有被回收,每次执行一次res,a的值就会自增一次
- res()函数可以记住并访问原来的词法作用域
什么是闭包
一个可以访问其他作用域的变量,并且能够记住所在的词法作用域的函数
怎么判断是一个闭包
当一个函数的返回值是另一个函数,这个返回的函数在原来所在的函数外部被执行了,并且访问了原来函数的变量,那这个上下文便产生了闭包环境。
闭包的优缺点
优点
- 实现了可以访问其他作用域变量,并且避免了全局变量对自身词法作用域变量的污染
- 可以把局部变量驻留在内存中一直保存着上一次执行的值,不会被垃圾回收机制回收,从而避免使用全局变量
缺点
- 局部变量会一直驻留在内存中不会被回收,导致内存被爆满,影响程序性能
使用场景
比如想要缩放窗口,触发onresize事件,需要让他只触发一次
window.onresize=function(){
console.log('只触发一次')
}
一般方法
window.onresize = function () {
// console.log('onresize') //只想触发一次
debounce(fn,1000)
}
var fn=function(){
console.log('只触发了一次');
}
var time=null
function debounce(fn,timeLong){
if(time){
clearTimeout(time)
time=''
}
time=setTimeout(()=>{
fn()
},timeLong)
}
二般方法
window.onresize=debounce(fn,1000)
function debounce(fn){
var timer=null
return function(){
if(timer){
clearTimeout(timer)
timer=null
}
timer=setTimeout(()=>{
fn()
},1000)
}
}
function fn(){
console.log('二班只触发一次');
}
老掉牙的方法
for (var i = 1; i <= 10; i++) {
((j) => {
setTimeout(() => {
console.log(j);
})
})(i)
}