javascript使用閉包模擬對(duì)象的私有屬性和方法
最近因?yàn)樽隽艘粋€(gè)項(xiàng)目,其中涉及到了js私有方法,這個(gè)概念在其語(yǔ)言里面是很常見的,很多語(yǔ)言都有private這個(gè)關(guān)鍵字,只要在一個(gè)類的前面加上private就表示申明了一個(gè)私有方法,但是javascript在面向?qū)ο蟮姆矫鏇]有那么多的特征,他沒有專門的private關(guān)鍵字,。要做到這一點(diǎn)就必須使用js自己的一些特性來(lái)變相的完成。
首先javascript里面有一個(gè)高級(jí)特性叫閉包,簡(jiǎn)單的說(shuō)js的閉包可以理解成是一種現(xiàn)象或者特性,一般出現(xiàn)在兩個(gè)函數(shù)嵌套的情況下,看例子:
function a(){
var eg = 1;
return function(){
alert(eg);
}
}
var c = a();
a函數(shù)里返回了一個(gè)函數(shù),返回的函數(shù)被全局作用域下的c接受了,此時(shí)因?yàn)榉祷氐暮瘮?shù)調(diào)用了a函數(shù)里面的eg變量,并且被全局作用域下的變量c引用,此時(shí)下形成閉包,a函數(shù)的內(nèi)存空間不會(huì)被收回,這個(gè)閉包的理解其實(shí)和js的垃圾回收機(jī)制有關(guān),js的垃圾回收其實(shí)是靠引用來(lái)計(jì)算的,比如我們申明了一個(gè)函數(shù),這個(gè)函數(shù)就會(huì)有一個(gè)引用指向他自己,當(dāng)函數(shù)運(yùn)行結(jié)束的時(shí)候銷毀引用,js如果發(fā)現(xiàn)沒有引用的函數(shù)就會(huì)銷毀這個(gè)函數(shù)的內(nèi)存空間,函數(shù)也就沒有了。我們上面的例子中首先a函數(shù)運(yùn)行,給eg賦值1,然后返回一個(gè)匿名函數(shù),到此a函數(shù)運(yùn)行完了,按照原有的理論,此時(shí)a函數(shù)應(yīng)該被銷毀,但是此時(shí)他返回了一個(gè)函數(shù),這個(gè)函數(shù)被全局下的變量c引用,c是不會(huì)被銷毀的,除非我們手動(dòng)銷毀,而且這個(gè)返回的函數(shù)引用了a函數(shù)的變量eg,js引擎會(huì)認(rèn)為eg依然是有用的,因?yàn)樗匀辉诒皇褂?,因此包含eg這個(gè)局部變量的函數(shù)a也不會(huì)被銷毀。
閉包的理解可能不是一下講的通的,這里其實(shí)還涉及到一個(gè)作用域的問(wèn)題,我記得以前有人說(shuō)返回的這個(gè)函數(shù)被c接收了,c是在全局作用下的,為什么調(diào)用c的時(shí)候會(huì)彈出a函數(shù)里面的eg,難道不應(yīng)該是全局作用域下的eg嗎?而且js的函數(shù)作用于是局部的,外部不能訪問(wèn)。其實(shí)這里有一個(gè)理論,記住就可以,js里的函數(shù)作用域取決于函數(shù)定義的位置,而不是函數(shù)調(diào)用的位置,也就是說(shuō),函數(shù)在什么地方定義的,他的作用域就決定了,不管他在什么地方調(diào)用,作用域都不會(huì)改變,返回的這個(gè)匿名函數(shù)是在a函數(shù)里面定義的,所以他的上級(jí)作用域就是這個(gè)a函數(shù),而不是全局作用域。
這里要說(shuō)的私有方法其實(shí)和閉包是有關(guān)系的,私有方法在其他語(yǔ)言里面是不被訪問(wèn)到的,除非有專門的接口,js的局部作用域里面的東西在正常情況下也是不能被外部訪問(wèn)到,但是上面例子顯示了,通過(guò)閉包的方式可以訪問(wèn)到,這樣我們就可以利用這個(gè)特性,看例子:
var book = (function(){
var page = 100;
return function(){
this.auther = 'dava';
this.price = 200;
this._page = function(){
alert(page);
}
}
})();
var a = new book();
a.auther//"dava"
a.price// 200
a.page//"wrong"
a._page()// 100
這里例子用了一個(gè)函數(shù)自動(dòng)執(zhí)行,一上來(lái)就執(zhí)行了一個(gè)匿名函數(shù),并且在匿名函數(shù)里面定義了一個(gè)局部變量page,然后又返回了一個(gè)匿名函數(shù),并且被全局作用域下的book變量接收,此時(shí)使用new 調(diào)用book就會(huì)生成一個(gè)新對(duì)象a。其中auther屬性和price屬性可以直接通過(guò)對(duì)象訪問(wèn),因?yàn)檫@些屬性都是new的時(shí)候直接定義在返回的對(duì)象身上的,而page屬性則沒有,因此不能反回,但此時(shí)如果我想訪問(wèn)page屬性,那就得依靠閉包了,返回的函數(shù)在外層的匿名函數(shù)里面,因此在返回的函數(shù)身上定義了一個(gè)方法叫_page,這個(gè)方法彈出了page屬性,按照js作用域的關(guān)系,當(dāng)前作用域找不到page,就會(huì)到上層作用域去尋找,這樣就找到了。通過(guò)這種方式我們就把私有方法和公有方法區(qū)分開了。
相關(guān)文章
詳解JavaScript UTC時(shí)間轉(zhuǎn)換方法
這篇文章主要介紹了JavaScript UTC時(shí)間轉(zhuǎn)換方法,介紹了本地時(shí)間到UTC時(shí)間的轉(zhuǎn)換、UTC日期到本地日期的轉(zhuǎn)換,感興趣的小伙伴們可以參考一下2016-01-01
canvas實(shí)現(xiàn)動(dòng)態(tài)小球重疊效果
在javascript運(yùn)動(dòng)系列中,詳細(xì)介紹了各種運(yùn)動(dòng),其中就包括碰壁運(yùn)動(dòng)。但是,如果用canvas去實(shí)現(xiàn),卻是另一種思路。本文將詳細(xì)介紹canvas動(dòng)態(tài)小球重疊效果。下面跟著小編一起來(lái)看下吧2017-02-02
JavaScript回調(diào)函數(shù)callback用法解析
這篇文章主要介紹了JavaScript回調(diào)函數(shù)callback用法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01
js設(shè)置cookie過(guò)期及清除瀏覽器對(duì)應(yīng)名稱的cookie
js設(shè)置cookie過(guò)期也就相當(dāng)于清除瀏覽器對(duì)應(yīng)名稱的cookie,下面有個(gè)不錯(cuò)的示例,感興趣的朋友可以參考下2013-10-10
layui 實(shí)現(xiàn)表單和文件上傳一起傳到后臺(tái)的例子
今天小編就為大家分享一篇layui 實(shí)現(xiàn)表單和文件上傳一起傳到后臺(tái)的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09
簡(jiǎn)單實(shí)現(xiàn)js懸浮導(dǎo)航效果
這篇文章主要教大家如何簡(jiǎn)單實(shí)現(xiàn)js懸浮導(dǎo)航效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
Jquery顏色選擇器ColorPicker實(shí)現(xiàn)代碼
這里我要分享一個(gè)自己修改的顏色選擇器,有需要的朋友參考下2012-11-11

