什么是闭包:
简单来说,闭包就是定义在一个函数内部的函数(函数的嵌套),内部函数可以访问外层函数的内部变量,外部函数return 内部函数。外部函数被其它外部调用。如下代码
function bibao(){
var a=0;
function bibaoInner(b){
alert(a+b)
}
return bibaoInner;
}
function bibaoAction(){
var c=bibao();
console.log(c(5));
}
bibaoAction();
「函数」和「函数内部能访问到的局部变量」,就是一个闭包。这里局部变量a 和函数bibaoInner就形成了闭包;又如下面代码
function bibao(c) {
var a = 0;
var pp = function bibaoInner(b) {
return a + c + b;
}
return pp;
},
bibao(2)(3);
return pp,是为了外面可以访问这个闭包。与闭包本身无关。
闭包如此简单,那闭包有什么特性?
全局变量不会被回收,局部变量在函数执行完成以后,函数内部的东西就会被销毁,除非被被另一个作用域所引用就不会被回收。看上面代码:bibao函数,a为局部变量,bibao(2)(3)执行,实际就是对bibao内部函数pp的执行,pp执行会引用到bibao中的a 。所以a不会被回收。
所以闭包占用内存,不易被释放。如下面代码:
function fun(){
var i=0;
return function(){
alert(i++);
}
}
fun();//返回一个函数
fun()();//d出0
fun()();//d出0
var f1=fun(),f2=fun();
f1();//d出0
f1();//d出1
f1();//d出2
f2();//d出0
再次调用f1(),也就是还在引用f1中i的变量,经过第一次调用f1,i++已经变成i=1;所以再次调用f1,会输出1 。
然后再调用f2(),按理说应该是2了。但不是,答案是0 。因为调用f2(),就相当于重新调用fun()()。而每一次调用fun(),变量i都会被重新赋值i=0;所以第二次调用f1,输出还是0。
为什么需要闭包?
局部变量无法共享和长久的保存,而全局变量可能造成变量污染。我们希望有一种机制既可以长久的保存变量又不会造成全局污染。所以我们就用到了闭包。当我们不用闭包是,可以将局部变量致空,从而释放内存,如下代码 :
f1=null;
f2=null;
什么情况下使用闭包?
经典例子:
for(var i=1; i<=10,i++){
setTimeout(function(){
console.log(i)
},1000)
}
//1秒后输出10个11,i是声明在全局作用中的,定时器中的匿名函数也是执行在全局作用域中,所以1秒之后,i的值已经发生了改变,每次都输出11了。
for(var i=1;i<=10;i++){
(function(j){
setTimeout(function(){
console.log(j);
},1000);
})(i)
}
//
// DOM操作、为元素的伪数组添加事件
let li = document.querySelectorAll('li');
for(var i = 0; i < li.length; i++) {
(function(i){
li[i].onclick = function() {
alert(i);
}
})(i)
}
1、闭包的应用比较典型是定义模块,我们将 *** 作函数暴露给外部,而细节隐藏在模块内部
function array() {
var arr = [];
this.add = function(val) {
if (typeof val == 'number') {
arr.push(val);
}
}
this.get = function(index) {
if (index < arr.length) {
return arr[index]
} else {
return null;
}
}
}
var arr=new array();
arr.add(1);
arr.add(2);
arr.add('xxx');
console.log(arr.get(1));
console.log(arr.get(2));
//arr引用array()
//arr调用相关函数 获取值
//发现arr[]的值没有被销毁,且下次使用的时候,会保留上一次的数据
2、setTimeOut原生第一个函数不能传参数,利用闭包就可以实现传参
function f1(a) {
function f2() {
console.log(a);
}
return f2;
}
var fun = f1(1);
setTimeout(fun,1000);//一秒之后打印出1
3、封装私有变量
function Animal(value){
var animal=value;
var setNum=0;
this.getName=function(){
return animal;
}
this.setName=function(value){
setNum++
animal=value
}
this.getNum=function(){
return setNum
}
}
var animal=new Animal("ni")
animal.setName("ho")
console.log(animal.getName())
console.log (animal.getNum())
4、防抖、节流
防抖,代码如下:
export const debounce = (fn, awaits) => {
let timer;
return function () {
console.log("进入防抖");
let context = this;
let args = arguments;
if (timer) {
clearTimeout(timer);
timer = null;
} else {
timer = setTimeout(function () {
fn.apply(context, args);
}, awaits);
}
};
};
节流版:
export const throttle = (func, wait) => {
console.log("进入节流")
let timeout;
return function () {
let context = this;
let args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
前端学习交流群,永久有效,需要的可以加jjljzh:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)