通俗地讲就是别人家有某个东西,你想拿到但是因为权限不够(不打死你才怪),但是你可以跟家里的孩子套近乎,通过他拿到!
这个家就是局部作用域,外部无法访问内部变量,孩子是返回对象,对家里的东西有访问权限,借助返回对象间接访问内部变量!
作用域:
分为全局作用域和局部作用域
局部作用域:
函数作用域:
function courage(){ const positivity}
函数可以访问全局作用域中的内容,但是函数内部声明的内容仅存在于函数作用域,仅供函数内部使用
块级作用域:
{ const negativity}
如果再代码任何位置用大括号括起一个变量,那么该变量也将被封闭,属于块级作用域
闭包
当在函数内部生命了内部函数,并将内部函数作为值返回,就会产生闭包
function foo(){ let a = "hello world"; function bar(){ console.log(a); }return bar;}let keith = foo();keith(); //hello world
将函数作为值传递,实际上就是打开了一条访问内部变量的通道,这个‘通道’说的就是内部函数对词法作用域的引用,这个引用就是闭包
闭包的本质:基于词法作用域,函数作为值传递
词法作用域:就是,按照代码书写时的样子,内部函数可以访问函数外面的变量。
引擎通过数据接口和算法表示一个函数,使得在代码解释执行时按照词法作用域的规则,可以访问外围的变量,这些变量就登记在相应的数据结构中。
这时我们再来理解一下闭包的概念:
闭包的概念:当函数可以记住并访问所在的词法作用域,函数在当前词法作用域之外执行,就会形成闭包
闭包的几种表现形式
1、返回一个函数
2、作为函数参数传递
3、回调函数
返回一个函数
var a = 1;
function foo(){
var a = 2;
// 这就是闭包
return function(){
console.log(a);
}
}
var bar = foo();
// 输出2,而不是1
bar();
作为函数传递参数
var a=1;
function foo(){
var a=2;
function baz(){
console.log(a);
}
bar(baz);
}
function bar(fn){
fn();
}
foo();
//输出2,而不是1
回调函数:在定时器、事件监听、Ajax请求、跨窗口通信、Web Workers或者任何异步中,只要使用了回调函数,实际上就是在使用闭包
//定时器
setTimeout(function timeHandler(){
console.log('timer');
},100)
//事件监听
$('#container').click(function(){
console.log('DOM Listener');
})
闭包的好处
先介绍一下全局变量和局部变量的优缺点 全局变量:可以重用、但是会造成全局污染而且容易被篡改。
局部变量:仅函数内使用不会造成全局污染也不会被篡改、不可以重用。
所以,全局变量和局部变量的优缺点刚好相对。闭包的出现正好结合了全局变量和局部变量的优点。