闭包那些事

今天在面试的时候被问到闭包,自己我的感受仍是挺懂的,一时半会忽然又懵逼不知道从何提及(WTF). 好吧那我接下来在从新记录下吧:git

其余时效优质文章,欢迎查阅github

专业名词解释:

在计算机中,闭包指引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在。

局限自定义: 在Javascript 中子函数中使用了其父函数或者外层函数的变量等就产生了一个闭包。这时外层变量的值能被子函数使用且外层变量在子函数未销毁以前一直被分配不会被释放。面试

说源头提及:

闭包的产生因为变量做用域链引发的(由词法做用域致使)。
 微信

JavaScript做用域:

在ES5及以前的语言规范中做用域分3种:闭包

  • 全局做用域
  • 局部(函数做用域)
  • eval做用域。

[注意:没有块级做用域]函数

在函数中定义的变量,就属于局部做用域,且只对函数范围内其余表达式可见。
而函数内部又可使用父函数中的变量这就是因为做用域链,当JavaScript查找与变量关联的值时,会遵循一个查找链。这个链是基于做用域的层次结构。 以下代码:spa

var a = "global variable"; 
( function () { 
    console.log(a); 
    var fn = function () { 
        var a = "local variable" 
        console.log(a);
    }     
    fn(); 
})()

//输出
//global variable
//local variable

咱们在window全局对象下声明了变量a,随后调用了一个当即执行函数,其中向控制台直接打印变量a,因为当即执行函数没有声明局部变量a因此致使JavaScript向其做用域链继续查找接着就在window对象中找到a变量并打印出它的值"global variable"。接着这个当即执行函数声明了一个局部函数变量再调用它,在这个函数变量中首先声明了一个局部变量a而后在向控制台输出a得值。JavaScript在执行时因为在fn函数做用域内部查找到了变量a就直接使用变量a的值因此打印出了local variable。code

值得注意的是:对象

  1. 这里其实有2个闭包环境一个是window对象和当即执行函数所建立的闭包;另外一个是当即执行函数和其内部声明的函数变量fn建立的闭包。
  2. 闭包其实就是个称呼,重要的是在这种场景下内部函数能够调用外部函数的变量,而这正是由于词法做用域链。
  3. 当闭包产生,在局部函数未被释放以前,被引用外部函数的变量就没法被释放。

清楚做用域的含义了吗???索引

那么咱们刚刚说的“词法“做用域又是什么。
其实词法就是指代环境:因为函数决定做用域,而且函数是一等公民能够直接用来参数传递等。那么做用域链是怎样来肯定的呢: 下面的话背熟了:
做用域链是根据函数定义时候的位置肯定的而不是在调用时。--这就是“词法”做用域

若是你还不懂闭包我TM。。。

最后咱们来看看几个老生长谈的基本栗子:

  • [闭包的影响]对一些li绑定点击事件并打印其索引,对比2断代码不解释:
var liListlength = 3; 
for(var i=0;i<liListlength;i++){ 
    var ele=document.querySelectorAll(".test > li")[i]; 
    ele.addEventListener("click",function(){ 
        alert("index is :" + i); 
    })         
}

var liListlength = 3; 
for(var i=0;i<liListlength;i++){ 
    var ele=document.querySelectorAll(".test > li")[i]; 
    ele.addEventListener("click",(function(i){ 
        return function(){ 
            alert("index is :" + i); 
        } 
    })(i))     
}
  • [闭包的妙用]模拟封装

咱们能够运用闭包模拟模块的实现,即咱们能够只暴露方法接口隐藏局部变量,具体以下:

var countMoudle = (function(){ 
var _count = 0; 

var plus = function(){ 
  _count++; 
}; 

var minus = function(){ 
  _count--; 
}; 

var print = function(){ 
    console.log(_count); 
} 

return { 
  plus: plus, 
  minus: minus, 
  print: print 

}; 
})();

countMoudle.print()  //0
countMoudle.plus()   
countMoudle.print()  //1
countMoudle.minus()
countMoudle.print()  //0

此时咱们只暴露出了方法名而没有暴露出变量属性,这时要对变量的修改只有经过接口方法调用。

最后

若有任何问题和建议欢迎发送至邮箱讨论:<Tommy.White.h.li@gmail.com>
编写不易,若您以为对您有帮助,欢迎打赏

微信:图片描述

支付宝:图片描述

相关文章
相关标签/搜索