闭包实际上是一种函数,闭包能做的,函数几乎都能做。
当一个内部函数被其外部函数之外的变量引用时,就形成了闭包
常见的闭包使用形式?
- 将函数作为另一个函数的返回值
function fn1() {
var num =10;
function fn2() {
num++;
console.log(num);
}
return fn2;
}
var f=fn1();
f();//11
f();//12
- 将函数的形参作为实参传递给另一个函数调用
最大的作用
- 可以读取函数内部的变量
- 让这些变量的值始终保存在内存中
产生:在嵌套内部函数定义执行完时就产生了(不是在调用)
死亡:在嵌套的内部函数成为垃圾对象时
如果想要从外界用到函数内部的局部变量,基本用法
<script>
/*
一个是可以读取函数内部的变量,
另一个就是让这些变量的值始终保持在内存中。
*/
function test1() {
var age = 19;//局部变量
return function () {
console.log(age);
}
}
var func = test1();//func的内容是一个函数
func();//19
console.log(test1());//输出的是function本身这个函数
</script>
封闭作用域
封闭作用域又称值为封闭空间,或小闭包和匿名函数自调。
基本格式
(function () {
})(); //为主
;(function () {
})();
+(function () {
})();
-(function () {
})();
//匿名函数自调
(function () {
console.log('1111');
})();
//控制台输出 1111
(function () {
var age = 19;
console.log(age);//19
})();
(function () {
var age = 'abc' // 若 age='abc' 则下面的function↓
console.log(age); //abc
})();
(function () {
//var age='哈哈哈';
console.log(age); // age is not defined || abc
})();
作用域链
可以从内(当前作用域)至外
高级排他
<script>
/*var allLis = document.getElementsByTagName('li');
for (var i = 0; i <allLis.length ; i++) {
allLis[i].addEventListener('mouseover',function () {
for (var j = 0; j < allLis.length; j++) {
allLis[j].className = '';
}
this.className = 'current';
});
}*/
var allLis = document.getElementsByTagName('li');
var lastOne = 0;
for (var i = 0; i < allLis.length; i++) {
(function (index) {
allLis[index].addEventListener('mouseover', function () {
//清除之前选中的
allLis[lastOne].className = '';
this.className = 'current';
lastOne = index;
});
})(i)
}
</script>
参数传递
<script>
function test(x) {
return function (y) {
alert(x + y);
}
}
test(10)(5);//15
----------------------------------------------
var left = 0,right =0,speed=50;
var lImg = document.getElementById('l');
var rImg = document.getElementById('r');
lImg.addEventListener('mousedown',function () {
left-=speed;
this.style.marginLeft = left+'px';
});
rImg.addEventListener('mousedown',function () {
right+=speed;
this.style.marginLeft = right+'px';
});
//等价于↓
-----------------------------------------------
function move(speed) {
var num = 0;
return function () {
num += speed;
this.style.marginLeft = num + 'px';
}
}
var lImg = document.getElementById('l');
var rImg = document.getElementById('r');
lImg.addEventListener('mousedown', move(-50));
rImg.addEventListener('mousedown', move(50));
</script>
函数节流
<script>
var timer =null;
window.onresize = function () {
clearTimeout(timer);
timer = setTimeout(function () {
console.log(document.documentElement.clientWidth);
},400);
}
-------------------------------------------
function throttle(fn,delay) {
var timer = null;
return function () {
clearInterval(timer);
timer=setTimeout(fn,delay);
}
}
window.onresize = throttle(function () {
console.log(document.documentElement.clientWidth);
},400)
</script>