介绍你下你理解的闭包?无论怎样!我最近听到不少次!感受是很差好总结一下无法面对那些犀利的追问!
若是以为闭包理解的很透彻,就直接跳到最后看题目!html
小红书的解释闭包是有权访问另外一个函数做用域中的变量的函数。明白了吗?就是一个函数,一个能够访问其余函数中变量的函数。因此常见的建立闭包的方式就是在一个函数内部建立另外一个函数。windows
function bag(num){ return function(){ return num } } var bagc = bag(12) console.log(bagc()) //12
能够看到在bag内部的匿名函数能够访问外部bag函数的变量num。数组
闭包能够用在许多地方。它的最大用处有两个,一个是能够读取函数内部的变量,另外一个就是让这些变量的值始终保持在内存中。闭包
function f1(){ var n=999; nAdd=function(){n+=1} function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999 nAdd(); //变量n被保存了 result(); // 1000
上面是阮一峰在文档中的一个例子,读取函数内部变量我以为用处通常吧,让变量保持在内存中的用处却是很多,像常用的that=this等。下面看一个常见的问题:app
for(var i = 0;i <10;i++){ setTimeout(()=>{ console.log(i) },1000) } //上面的代码咱们但愿按照索引值打印,结果却打印了10个10,为何就不解释了,i是全局变量。 //换成下面的写法,就能解决问题,正是由于闭包 让变量的值始终保持在内存中,每一个i都存在了num这个局部变量中 for(var i = 0;i <10;i++){ (function(num){ setTimeout(()=>{ console.log(num) },1000) })(i) }
闭包虽然在解决一些问题上有好处,可是由此引起的一些问题要注意,并且因为闭包会携带外部函数做用域,因此内存占用比较大,因此尽可能少用、慎用闭包。dom
正是由于闭包可使用外部变量,因此下面的代码中,返回的匿名函数中对变量i的使用将会是最终的值,数组中存放的函数的返回值将都会是10。函数
function test() { var result = []; for(var i = 0; i<10; i++){ result.[i] = function () { return i; } } return result }
须要将上述代码改写成以下:测试
function test() { var result = []; for(var i = 0; i<10; i++){ result.[i] = function (num) { return function() { console.info(num); } }(i) } return result }
此时访问的num,是上层函数执行环境的num,数组有10个函数对象,每一个对象的执行环境下的number都不同。this
匿名函数的执行具备全局性,因此闭包函数的this通常指向window;code
var object = { name: "object", getName:function() { return function() { console.info(this.name) } } } object.getName()() // underfined // 由于里面的闭包函数是在window做用域下执行的,也就是说,this指向windows
能够改写成以下:
var object = { name: "object", getName:function() { var that = this; return function() { console.info(that.name) } } } object.getName()() // object
若是闭包在做用域链中保存着html元素,则该元素内存将没法自动销毁。
function showId() { var el = document.getElementById("app") el.onclick = function(){ aler(el.id) // 这样会致使闭包引用外层的el,当执行完showId后,el没法释放 } } // 改为下面 function showId() { var el = document.getElementById("app") var id = el.id el.onclick = function(){ aler(id) // 这样会致使闭包引用外层的el,当执行完showId后,el没法释放 } el = null // 主动释放el }
好了,看到这里是否是感受对闭包理解的很到位了?别着急,看看这两个小问题测试一下!
var Test = { close:function(val){ return function (z){ return ++ val +z } } } var getClose = function(val){ return Test[val] } var fn = getClose('close') var cover = fn(100) console.log(cover(200)) console.log(cover(300)) console.log(fn(100)(200)) console.log(fn(100)(200)) console.log(getClose('close')(100)(300)) //输出结果见结尾处
var container1 = document.getElementById('container1') var container2 = document.getElementById('container2') var container3 = document.getElementById('container3') var container4 = document.getElementById('container4') var container5 = document.getElementById('container5') var innerHTML = 'window的html' var events = { innerHTML:'我是events', getHtml:function (){ console.log(this.innerHTML) }, setFun:function(){ return this.getHtml }, proxy:function(){ var self = this; return function(){ self.getHtml() } } } container1.onclick = events.getHtml; container2.onclick = events.setFun(); container3.onclick = events.proxy(); container4.onclick = function(){ window.setTimeout(events.setFun(),0) } container5.onclick = function(){ window.setTimeout(events.proxy(),0) }
还ok?有没有被绕晕!晕了就打开电脑敲吧
看一下输出结果吧 第一题:401 402 301 301 401 第二题:container container2 我是events window的html 我是events