摘要:?jiǎn)栴}匿名函數(shù)的執(zhí)行具有全局性,所以閉包函數(shù)的一般指向,因?yàn)槔锩娴拈]包函數(shù)是在作用域下執(zhí)行的,也就是說(shuō),指向可以改寫(xiě)成如下,內(nèi)存泄漏問(wèn)題如果閉包在作用域鏈中保存著元素,則該元素內(nèi)存將無(wú)法自動(dòng)銷毀。
介紹你下你理解的閉包?不管怎樣!我最近聽(tīng)到很多次!感覺(jué)是不好好總結(jié)一下沒(méi)法面對(duì)那些犀利的追問(wèn)!
如果覺(jué)得閉包理解的很透徹,就直接跳到最后看題目!
小紅書(shū)的解釋閉包是有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中的變量的函數(shù)。明白了嗎?就是一個(gè)函數(shù),一個(gè)可以訪問(wèn)其他函數(shù)中變量的函數(shù)。所以常見(jiàn)的創(chuàng)建閉包的方式就是在一個(gè)函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù)。
function bag(num){ return function(){ return num } } var bagc = bag(12) console.log(bagc()) //12
可以看到在bag內(nèi)部的匿名函數(shù)可以訪問(wèn)外部bag函數(shù)的變量num。
2.閉包的用處閉包可以用在許多地方。它的最大用處有兩個(gè),一個(gè)是可以讀取函數(shù)內(nèi)部的變量,另一個(gè)就是讓這些變量的值始終保持在內(nèi)存中。
function f1(){ var n=999; nAdd=function(){n+=1} function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999 nAdd(); //變量n被保存了 result(); // 1000
上面是阮一峰在文檔中的一個(gè)例子,讀取函數(shù)內(nèi)部變量我覺(jué)得用處一般吧,讓變量保持在內(nèi)存中的用處倒是不少,像經(jīng)常使用的that=this等。下面看一個(gè)常見(jiàn)的問(wèn)題:
for(var i = 0;i <10;i++){ setTimeout(()=>{ console.log(i) },1000) } //上面的代碼我們希望按照索引值打印,結(jié)果卻打印了10個(gè)10,為什么就不解釋了,i是全局變量。 //換成下面的寫(xiě)法,就能解決問(wèn)題,正是因?yàn)殚]包 讓變量的值始終保持在內(nèi)存中,每個(gè)i都存在了num這個(gè)局部變量中 for(var i = 0;i <10;i++){ (function(num){ setTimeout(()=>{ console.log(num) },1000) })(i) }3.使用閉包需要注意的點(diǎn)
閉包雖然在解決一些問(wèn)題上有好處,但是由此引發(fā)的一些問(wèn)題要注意,而且由于閉包會(huì)攜帶外部函數(shù)作用域,所以內(nèi)存占用比較大,所以盡量少用、慎用閉包。
1.變量問(wèn)題正是因?yàn)殚]包可以使用外部變量,所以下面的代碼中,返回的匿名函數(shù)中對(duì)變量i的使用將會(huì)是最終的值,數(shù)組中存放的函數(shù)的返回值將都會(huì)是10。
function test() { var result = []; for(var i = 0; i<10; i++){ result.[i] = function () { return i; } } return result }
需要將上述代碼改寫(xiě)成如下:
function test() { var result = []; for(var i = 0; i<10; i++){ result.[i] = function (num) { return function() { console.info(num); } }(i) } return result }
此時(shí)訪問(wèn)的num,是上層函數(shù)執(zhí)行環(huán)境的num,數(shù)組有10個(gè)函數(shù)對(duì)象,每個(gè)對(duì)象的執(zhí)行環(huán)境下的number都不一樣。
2.this問(wèn)題匿名函數(shù)的執(zhí)行具有全局性,所以閉包函數(shù)的this一般指向window;
var object = { name: "object", getName:function() { return function() { console.info(this.name) } } } object.getName()() // underfined // 因?yàn)槔锩娴拈]包函數(shù)是在window作用域下執(zhí)行的,也就是說(shuō),this指向windows
可以改寫(xiě)成如下:
var object = { name: "object", getName:function() { var that = this; return function() { console.info(that.name) } } } object.getName()() // object3.內(nèi)存泄漏問(wèn)題
如果閉包在作用域鏈中保存著html元素,則該元素內(nèi)存將無(wú)法自動(dòng)銷毀。
function showId() { var el = document.getElementById("app") el.onclick = function(){ aler(el.id) // 這樣會(huì)導(dǎo)致閉包引用外層的el,當(dāng)執(zhí)行完showId后,el無(wú)法釋放 } } // 改成下面 function showId() { var el = document.getElementById("app") var id = el.id el.onclick = function(){ aler(id) // 這樣會(huì)導(dǎo)致閉包引用外層的el,當(dāng)執(zhí)行完showId后,el無(wú)法釋放 } el = null // 主動(dòng)釋放el }4.閉包練習(xí)題
好了,看到這里是不是感覺(jué)對(duì)閉包理解的很到位了?別著急,看看這兩個(gè)小問(wèn)題測(cè)試一下!
1.與函數(shù)調(diào)用結(jié)合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)) //輸出結(jié)果見(jiàn)結(jié)尾處2.與dom結(jié)合
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?有沒(méi)有被繞暈!暈了就打開(kāi)電腦敲吧
看一下輸出結(jié)果吧 第一題:401 402 301 301 401 第二題:container container2 我是events window的html 我是events
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/106511.html
摘要:在的開(kāi)發(fā)者工具中,通過(guò)斷點(diǎn)調(diào)試,我們能夠非常方便的一步一步的觀察的執(zhí)行過(guò)程,直觀感知函數(shù)調(diào)用棧,作用域鏈,變量對(duì)象,閉包,等關(guān)鍵信息的變化。其中表示當(dāng)前的局部變量對(duì)象,表示當(dāng)前作用域鏈中的閉包。 showImg(https://segmentfault.com/img/remote/1460000008404321); 在前端開(kāi)發(fā)中,有一個(gè)非常重要的技能,叫做斷點(diǎn)調(diào)試。 在chrome...
摘要:什么是閉包閉包是函數(shù)廢話閉包還是一個(gè)可以訪問(wèn)函數(shù)中變量的函數(shù)。每個(gè)閉包都是引用自己詞法作用域內(nèi)的變量。每次調(diào)用其中一個(gè)計(jì)數(shù)器時(shí),通過(guò)改變這個(gè)變量的值,會(huì)改變這個(gè)閉包的詞法環(huán)境。然而在一個(gè)閉包內(nèi)對(duì)變量的修改,不會(huì)影響到另外一個(gè)閉包中的變量。 為什么要寫(xiě)深入理解 筆者并不是大神,只是一個(gè)在校的大三學(xué)生。開(kāi)始寫(xiě)深入理解系列是為了給js的一些重難點(diǎn)知識(shí)進(jìn)行梳理,而不是每次面試之前都將這些知識(shí)重...
摘要:插件開(kāi)發(fā)前端掘金作者原文地址譯者插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡(jiǎn)單的方式。提供了與使用掌控異步前端掘金教你使用在行代碼內(nèi)優(yōu)雅的實(shí)現(xiàn)文件分片斷點(diǎn)續(xù)傳。 Vue.js 插件開(kāi)發(fā) - 前端 - 掘金作者:Joshua Bemenderfer原文地址: creating-custom-plugins譯者:jeneser Vue.js插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡(jiǎn)單的方式。插....
摘要:他的組成如下對(duì)的就是你關(guān)注的那個(gè)變量對(duì)象作用域鏈跟閉包相關(guān)由于是單線程的,一次只能發(fā)生一件事情,其他事情會(huì)放在指定上下文棧中排隊(duì)。 閉包和this,是兩個(gè)相當(dāng)高頻的考點(diǎn),然而你有沒(méi)有想過(guò),實(shí)際上他們兩個(gè)都跟同一個(gè)知識(shí)點(diǎn)相關(guān)? 有請(qǐng)我們的這篇文章的主角,執(zhí)行上下文 執(zhí)行上下文 執(zhí)行上下文是什么 可以簡(jiǎn)單理解執(zhí)行上下文是js代碼執(zhí)行的環(huán)境,當(dāng)js執(zhí)行一段可執(zhí)行代碼時(shí),會(huì)創(chuàng)建對(duì)應(yīng)的執(zhí)行上下文...
摘要:然而,異步函數(shù)不會(huì)立即被推入調(diào)用堆棧,而是會(huì)被推入任務(wù)隊(duì)列,并在調(diào)用堆棧為空后執(zhí)行。將事件從任務(wù)隊(duì)列傳輸?shù)秸{(diào)用堆棧稱為事件循環(huán)。我們調(diào)用接受和或返回另一個(gè)函數(shù)稱為高階函數(shù)的函數(shù)。 為了保證可讀性,本文采用意譯而非直譯 想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳GitHub博客,一年百來(lái)篇優(yōu)質(zhì)文章等著你! 1.如何理解 JS 中的this關(guān)鍵字? JS 初學(xué)者總是對(duì) this 關(guān)鍵字感到困惑,因?yàn)榕c其他現(xiàn)...
閱讀 1255·2023-04-26 02:38
閱讀 941·2023-04-25 20:13
閱讀 3594·2021-11-19 11:31
閱讀 2401·2019-08-30 15:55
閱讀 2726·2019-08-30 14:11
閱讀 3163·2019-08-30 13:45
閱讀 1379·2019-08-29 18:41
閱讀 1151·2019-08-29 16:18