前言
闭包能够防止无意识的更改了变量,防止变量的污染
一、Js 中的闭包
闭包:函数内套函数,并且内层的函数是在外层的函数体内进行声明的,内层的函数使用了外层函数的局部变量。
闭包的结构是:函数内套函数,这两个函数之间是父子关系的才算,
- 意思外层是一个函数,内层的函数是在外层函数内进行的声明。这样才算是闭包的函数套函数。
- 易错的地方在于,外层的函数和内层的函数属于同级的关系,都是在一个作用域进行的声明,但是在外层函数内调用了同级的内层函数,这样的结构不是闭包结构的函数套函数。
二、垃圾回收和闭包
垃圾回收在闭包中的使用,在 js 中,全局变量永远不会回收的,又因为全局变量可以在脚本内的任何一个地方使用到,所以太多的全局变量会占用比较多的内存。
另外,过多的闭包也会造成内存泄漏,因为使用闭包的方式需要将返回的函数赋值给一个全局变量,这样因为有全局变量在使用这个函数,所以函数的作用域不会被释放,多次调用才可以在之前的基础上进行运算。
如果并没有将闭包返回的函数赋值给一个全局变量,而是直接使用两个括号来调用的话,得到的都是调用一次的结果,并不会在之前的基础上进行运算。因为函数作用域作为局部作用域,在调用一次后,因为没有地方在使用了,所以会被垃圾回收掉,每次调用就是重新开始进行运算。
局部作用域不会一直占用内存空间。因为局部作用域在函数调用的时候才会进行创建,函数执行结束之后就会被释放。
二、闭包示例
- 闭包结构可以改变外层函数的值
function getNum(){
var n = 0;
function add(){
return n++;
}
return add;
};
var c=getNum();
console.log(c()); // 0
console.log(c()); // 1
console.log(c()); // 2
function fn(){
var num=3;
return function(){
var n=0;
console.log(n++);
console.log(++num);
}
}
var fn1 = fn();
fn1(); // 0 4
fn1(); // 0 5
- 注意两种调用闭包的方式,是一个易错点
function init(){
var n=100;
console.log("外部"+n);
function display(){
var num=0;
console.log(n++);
console.log(num++);
}
return display;
}
// 注意这两种方式执行两次的结果不一样
// 第一种
// init(); //外部100 100 0
// init(); //外部100 100 0
// 第二种
// var c = init(); // 外部100
// c(); // 100 0
// c(); // 101 0
总结
总结了如何判断闭包结构,用垃圾回收机制来解释闭包调用方式的不同