js中的闭包

123 阅读3分钟

通俗地讲就是别人家有某个东西,你想拿到但是因为权限不够(不打死你才怪),但是你可以跟家里的孩子套近乎,通过他拿到!
这个家就是局部作用域,外部无法访问内部变量,孩子是返回对象,对家里的东西有访问权限,借助返回对象间接访问内部变量!

作用域:

分为全局作用域和局部作用域

局部作用域:

函数作用域:

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');
})

闭包的好处

先介绍一下全局变量和局部变量的优缺点 全局变量:可以重用、但是会造成全局污染而且容易被篡改。
局部变量:仅函数内使用不会造成全局污染也不会被篡改、不可以重用。
所以,全局变量和局部变量的优缺点刚好相对。闭包的出现正好结合了全局变量和局部变量的优点。