前言
学到javascript的时候,不可避免的遇到了闭包,那么闭包到底是什么?也有童鞋提到闭包在面试过程中几乎是必问的问题,那么今天我们就来说说闭包.
一、闭包的定义
javascript权威指南:函数对象可以通过作用域链互相关联起来,函数体内部的变量都可以保存在函数作用域内.从技术的角度讲:所有的JavaScript函数都是闭包:它们都是对象,它们都关联到作用域链.
MDN:闭包可以让你从内部函数访问外部函数的作用域.有函数就有闭包.
广义:有函数就有闭包;
狭义:函数调用完成后,该被销毁的对象,由于引用(作为return的返回值),导致没有被销毁.
那么我们可以说:闭包=函数 + 函数周围的环境组成(执行的上下文).
二、特点
优点:
可以在外部访问函数内部的变量;
可以避免使用全局变量,防止全局污染.
缺点:
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大;
由于IE的bug,可能导致内存泄露.
三、闭包
举个🌰
let name = "mark";
function outer() {
let name = "john";
function inner() {
console.log(name);
}
inner();
}
outer();//john
在这个例子中,调用outer
函数,在函数中执行调用inner
函数,输出name
,但是在inner
的函数作用域中,没有name
,它向上一层函数作用域查找,得到name=john
.outer
调用完成后,outer
函数本应该被回收,但这时候闭包产生了,并阻止了变量和函数被回收.
在闭包的特点中我们说了可以通过闭包,在外部访问函数内部的变量,我们来看下一个例子:
function outer(){
var num = 999;
function inner(){
console.log(num);
}
return inner;
}
var result = outer();
result();//999
我们可以在函数内部添加一个函数,使用内部的函数调用局部变量,并返回这个局部变量,那么外部就可以获取到这个变量了.
四、例子
仔细看看下面的这些例子,答案和你的一样吗?
function outer(){
let i = 0;
function inner(){
console.log(++i);
}
return inner;
}
let fn1=outer();
fn1();//1
fn1();//2
fn1();//3
let fn2 =outer();
fn2();//1
fn2();//2
fn2();//3
function outer() {
var num = 2;
var inner = function () {
console.log(num);
}
num++;
console.log(num);
return inner;
}
var fn = outer();//3
fn();//3
function constfuncs(){
var funcs = [];
for(var i =0;i<5;i++){
funcs[i]=function(){return i;};
}
return funcs;
}
var funcs = constfuncs();
for(let i = 0;i<funcs.length;i++){
console.log(funcs[i]());//5 5 5 5 5
}
五、闭包的应用场景
1.柯里化
2.模块化
总结
那么通过以上的一些例子和定义,我们大概对闭包有了了解:闭包可以让你从内部函数访问外部函数的作用域.也可以通过闭包在外部环境访问局部环境的变量,另外注意不要随意改变父函数内部变量的值.