JavaScript閉包和回調(diào)詳解
一、閉包
閉包(closure)是Javascript語言的一個(gè)難點(diǎn),也是它的特色,很多高級(jí)應(yīng)用都要依靠閉包實(shí)現(xiàn)。
閉包有三個(gè)特性:
1.函數(shù)嵌套函數(shù);
2.函數(shù)內(nèi)部可以引用外部的參數(shù)和變量;
3.參數(shù)和變量不會(huì)被垃圾回收機(jī)制回收。
閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù),創(chuàng)建閉包的最常見的方式就是在一個(gè)函數(shù)內(nèi)創(chuàng)建另一個(gè)函數(shù),通過另一個(gè)函數(shù)訪問這個(gè)函數(shù)的局部變量。使用閉包有一個(gè)優(yōu)點(diǎn),也是它的缺點(diǎn),就是可以把局部變量駐留在內(nèi)存中,可以避免使用全局變量。全局變量在每個(gè)模塊都可調(diào)用,這勢(shì)必將是災(zāi)難性的。所以推薦使用私有的,封裝的局部變量。一般函數(shù)執(zhí)行完畢后,局部活動(dòng)對(duì)象就被銷毀,內(nèi)存中僅僅保存全局作用域。但閉包的情況不同!
示例一:
//閉包就是一個(gè)函數(shù)的返回值為另外一個(gè)函數(shù),在outer外部可以通過這個(gè)返回的函數(shù)訪問outer內(nèi)的局部變量.
function outer(){ var val = 0; return function (){ val += 1; document.write(val + "<br />"); }; } var outObj = outer(); outObj();//1,執(zhí)行val += 1后,val還在 outObj();//2 outObj = null;//val 被回收 var outObj1 = outer(); outObj1();//1 outObj1();//2
閉包會(huì)使變量始終保存在內(nèi)存中,如果不當(dāng)使用會(huì)增大內(nèi)存消耗(如果上例中定義很多outer(),則內(nèi)存中會(huì)保存很多val變量)。
javascript的垃圾回收原理:
(1)、在javascript中,如果一個(gè)對(duì)象不再被引用,那么這個(gè)對(duì)象就會(huì)被GC回收;
(2)、如果兩個(gè)對(duì)象互相引用,而不再被第3者所引用,那么這兩個(gè)互相引用的對(duì)象也會(huì)被回收。
那么使用閉包有什么好處呢?使用閉包的好處是:
1.希望一個(gè)變量長(zhǎng)期駐扎在內(nèi)存中
2.避免全局變量的污染
3.私有成員的存在
二、回調(diào)
回調(diào)函數(shù)原理:我現(xiàn)在出發(fā),到了通知你”。這是一個(gè)異步的流程,“我出發(fā)”這個(gè)過程中(函數(shù)執(zhí)行),“你”可以去做任何事,“到了”(函數(shù)執(zhí)行完畢)“通知你”(回調(diào))進(jìn)行之后的流程。
示例一:
function doSomething(callback){ callback(1,2); } function numberAdd(a,b){ document.write(a+b); } doSomething(numberAdd);//3
示例二:
function Thing(name){ this.name = name; }
//在Thing類里加入doSomething方法,這里使用了構(gòu)造器調(diào)用模式
Thing.prototype.doSomething = function(callback){ callback(this.name); }; function showName(name){ document.write(name); } var t = new Thing("zhangsan"); t.doSomething(showName);//zhangsan
如果你有一個(gè)數(shù)字組成的數(shù)組,你想寫個(gè)排序的公共方法,但是排序方式(從小到大或從大到?。┦钦{(diào)用該排序方法的人決定。實(shí)現(xiàn)該排序方法可以用回調(diào)來實(shí)現(xiàn),當(dāng)然你可以寫2個(gè)方法,一個(gè)是從小到大的排序,一個(gè)是從大到小的排序方法?;卣{(diào)個(gè)人認(rèn)為就是將決定權(quán)交給了實(shí)際業(yè)務(wù)開發(fā)工程師,由他來決定怎么去處理,這種思路跟我們平常接觸的不同,有點(diǎn)不習(xí)慣,但是這種思路在異步編程中特別能看出它的好處,不知道我這么理解是否正確。下面示例代碼就是回調(diào)的典型使用場(chǎng)合:
var arr = [25,13,33,8,23,32]; Array.prototype.sort = function(callback){ var arr = this; var i = 0;//i在這里定義與在for循環(huán)的括號(hào)內(nèi)(for(var i = 0; i < ...))定義是一樣的 for(; i < arr.length-1; i++){ var j = i + 1; for(; j < arr.length;j++){ if(callback(arr[i],arr[j])){ var temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } return arr; }; //a-b>0表示數(shù)組從小到大排序 arr.sort(function(a,b){ return a - b > 0; }); document.write(arr.join(",") + "<br />");//8,13,23,25,32,33 //b-a>0表示數(shù)組從大到小排序 arr.sort(function(a,b){ return b - a > 0; }); document.write(arr.join(","));//33,32,25,23,13,8
相關(guān)文章
JS實(shí)現(xiàn)選項(xiàng)卡實(shí)例詳解
這篇文章主要介紹了JS實(shí)現(xiàn)選項(xiàng)卡的方法,結(jié)合實(shí)例形式詳細(xì)講述了JavaScript實(shí)現(xiàn)選項(xiàng)卡的布局與功能實(shí)現(xiàn)的完整步驟及相關(guān)技巧,需要的朋友可以參考下2015-11-11基于JS實(shí)現(xiàn)導(dǎo)航條flash導(dǎo)航條
flash導(dǎo)航條在網(wǎng)站建設(shè)中應(yīng)用比較廣泛,此種效果給瀏覽者帶來極好的視覺效果,非常棒,下面小編給大家介紹基于JS實(shí)現(xiàn)導(dǎo)航條flash導(dǎo)航條,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧2016-06-06JS實(shí)現(xiàn)返回上一頁并刷新頁面的方法分析
這篇文章主要介紹了JS實(shí)現(xiàn)返回上一頁并刷新頁面的方法,結(jié)合實(shí)例形式分析了javascript針對(duì)移動(dòng)端、PC端瀏覽器的頁面緩存刷新相關(guān)操作技巧,需要的朋友可以參考下2019-07-07uniapp發(fā)送formdata表單請(qǐng)求2種方法(全網(wǎng)最簡(jiǎn)單方法)
這篇文章主要給大家介紹了關(guān)于uniapp發(fā)送formdata表單請(qǐng)求2種方法的相關(guān)資料,本文介紹的方法應(yīng)該是全網(wǎng)最簡(jiǎn)單方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09js小數(shù)計(jì)算小數(shù)點(diǎn)后顯示多位小數(shù)的實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄猨s小數(shù)計(jì)算小數(shù)點(diǎn)后顯示多位小數(shù)的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-05-05js取兩個(gè)數(shù)組的交集|差集|并集|補(bǔ)集|去重示例代碼
求兩個(gè)集合的補(bǔ)集、交集、差集、并集等等在實(shí)際應(yīng)用中經(jīng)常會(huì)使用到,下面與大家分享下具體的實(shí)現(xiàn)代碼,感興趣的朋友可以參考下,希望對(duì)大家有所幫助2013-08-08在table中插入多行的js代碼(與insertAdjacentHTML相似的功能)
在table中插入多行,能使用與insertAdjacentHTML相似的功能2010-06-06