闭包理解
闭包
刚学过的闭包,分享一下闭包的理解
1.什么是闭包?
闭包就是一个函数,也可以说闭包是一个引用关系,可以理解为一个作用域可以访问另一个函数的局部变量。
代码:
function fn() {
var num = 10;
function fun() {
console.log(num);
}
fun();
}
fn();
函数调用后,运行结果为10;
可以理解为 fun函数内部作用域访问到了fn函数内部的私有变量num,fn函数调用后,访问到了内部的局部变量。
这就引出了闭包产生的条件。
2.闭包的产生条件?
a.函数的嵌套;
b.内部函数 引用外部函数的局部变量;
c.调用外部函数;
3.闭包的作用
a. 延长外部函数变量对象的生命周期(也可以认为延伸了变量的作用范围);
b. 让函数外部可以操作(读写)到函数内部的数据(变量/函数),通过闭包间接的操作;
c.注意: 浏览器为了性能后期将外部函数中不被内部函数使用的变量清除了;
一段代码当中 究竟存在几套闭包机制 取决于外部函数调用了几次
代码块一
function fn() {
var a = 0;
function fn1() {
a ;
console.log(a)
}
return fn1;
}
var f = fn();
f();
f();
f();
解析:因为fn函数只调用了一次,创建了一次执行环境,后续的执行全在这一次创建的执行环境里,所以a ,也在原有的基础上增加。
**所以输出结果为 1,2,3;**闭包机制只有一套
代码块二
function fn() {
var a = 0;
function fn1() {
a ;
console.log(a)
}
return fn1;
}
fn();
fn();
fn();
解析:fn函数被调用了三次,每调用一次,就 创建一次新的执行环境,执行完成好进行销毁,所以每次调用a就从0开始 ,所以输出结果为1,1,1;闭包机制有三套
3.常见的闭包
a. 将函数作为另一个函数的返回值;
b. 将函数作为实参传递给另一个函数调用;
c. 使用闭包实现私有方法操作独立的私有属性;
看如下代码
functionc fn(){
var num =10;
function fun(){
console.log(num);
}
return fun;
}
var f = fn();
console.log(f);
console.log(f());
将函数作为另一个函数的返回值;
解析
var f =fn();
fn();//fn 运行 返回值是fun函数
var f =function fun(){
console.log(num);
}
所以console.log(f)打印出来的是 10
因为 fun函数没有返回值,先运行一遍fun函数,再打印出fun函数的返回值;所以console.log(f());打印出来的值是 10,undefined
4.闭包的生命周期
1. 产生: 在嵌套内部函数定义完时就产生了(不是在调用),外部函数调用的时候;
2. 死亡: 在嵌套的内部函数成为垃圾对象时;
5.闭包的缺点和解决(内存泄漏和内存溢出)
内存泄漏 : 内存无法释放;
内存溢出 : 内存被撑爆;
f = null; 解决方式;让闭包机制清除,必须删除外部函数调用的时候生成的(定义的那个对应内部函数);
6.闭包面试题
代码段1
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
return function() {
return this.name;
};
}
};
console.log(object.getNameFunc()());
解析
//解析
var f = object.getNameFunc();
var f = function() {
return this.name;
}
f();
function() {
return this.name;
}(); //相当于立即执行函数 this指向的是window
此题没有用到闭包
所以输出结果为 The Window;
代码段2
var name2 = "The Window";
var object2 = {
name2: "My Object",
getNameFunc: function () {
var that = this;
return function () {
return that.name2;
};
}
};
console.log(object2.getNameFunc()());
解析
典型的一个作用域可以访问另一个函数的局部变量。是闭包
var that =this;
这个this指的调用者object2对象,所以that也是object2对象,所以that.name2指的是object2的name属性。输出结果为 My Object;