javascript使用閉包模擬對象的私有屬性和方法
最近因為做了一個項目,其中涉及到了js私有方法,這個概念在其語言里面是很常見的,很多語言都有private這個關(guān)鍵字,只要在一個類的前面加上private就表示申明了一個私有方法,但是javascript在面向?qū)ο蟮姆矫鏇]有那么多的特征,他沒有專門的private關(guān)鍵字,。要做到這一點就必須使用js自己的一些特性來變相的完成。
首先javascript里面有一個高級特性叫閉包,簡單的說js的閉包可以理解成是一種現(xiàn)象或者特性,一般出現(xiàn)在兩個函數(shù)嵌套的情況下,看例子:
function a(){ var eg = 1; return function(){ alert(eg); } } var c = a();
a函數(shù)里返回了一個函數(shù),返回的函數(shù)被全局作用域下的c接受了,此時因為返回的函數(shù)調(diào)用了a函數(shù)里面的eg變量,并且被全局作用域下的變量c引用,此時下形成閉包,a函數(shù)的內(nèi)存空間不會被收回,這個閉包的理解其實和js的垃圾回收機制有關(guān),js的垃圾回收其實是靠引用來計算的,比如我們申明了一個函數(shù),這個函數(shù)就會有一個引用指向他自己,當(dāng)函數(shù)運行結(jié)束的時候銷毀引用,js如果發(fā)現(xiàn)沒有引用的函數(shù)就會銷毀這個函數(shù)的內(nèi)存空間,函數(shù)也就沒有了。我們上面的例子中首先a函數(shù)運行,給eg賦值1,然后返回一個匿名函數(shù),到此a函數(shù)運行完了,按照原有的理論,此時a函數(shù)應(yīng)該被銷毀,但是此時他返回了一個函數(shù),這個函數(shù)被全局下的變量c引用,c是不會被銷毀的,除非我們手動銷毀,而且這個返回的函數(shù)引用了a函數(shù)的變量eg,js引擎會認為eg依然是有用的,因為他仍然在被使用,因此包含eg這個局部變量的函數(shù)a也不會被銷毀。
閉包的理解可能不是一下講的通的,這里其實還涉及到一個作用域的問題,我記得以前有人說返回的這個函數(shù)被c接收了,c是在全局作用下的,為什么調(diào)用c的時候會彈出a函數(shù)里面的eg,難道不應(yīng)該是全局作用域下的eg嗎?而且js的函數(shù)作用于是局部的,外部不能訪問。其實這里有一個理論,記住就可以,js里的函數(shù)作用域取決于函數(shù)定義的位置,而不是函數(shù)調(diào)用的位置,也就是說,函數(shù)在什么地方定義的,他的作用域就決定了,不管他在什么地方調(diào)用,作用域都不會改變,返回的這個匿名函數(shù)是在a函數(shù)里面定義的,所以他的上級作用域就是這個a函數(shù),而不是全局作用域。
這里要說的私有方法其實和閉包是有關(guān)系的,私有方法在其他語言里面是不被訪問到的,除非有專門的接口,js的局部作用域里面的東西在正常情況下也是不能被外部訪問到,但是上面例子顯示了,通過閉包的方式可以訪問到,這樣我們就可以利用這個特性,看例子:
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
這里例子用了一個函數(shù)自動執(zhí)行,一上來就執(zhí)行了一個匿名函數(shù),并且在匿名函數(shù)里面定義了一個局部變量page,然后又返回了一個匿名函數(shù),并且被全局作用域下的book變量接收,此時使用new 調(diào)用book就會生成一個新對象a。其中auther屬性和price屬性可以直接通過對象訪問,因為這些屬性都是new的時候直接定義在返回的對象身上的,而page屬性則沒有,因此不能反回,但此時如果我想訪問page屬性,那就得依靠閉包了,返回的函數(shù)在外層的匿名函數(shù)里面,因此在返回的函數(shù)身上定義了一個方法叫_page,這個方法彈出了page屬性,按照js作用域的關(guān)系,當(dāng)前作用域找不到page,就會到上層作用域去尋找,這樣就找到了。通過這種方式我們就把私有方法和公有方法區(qū)分開了。
相關(guān)文章
在光標(biāo)處插入字符串的實現(xiàn)代碼 兼容IE,Firefox
在光標(biāo)處插入字符串,一般用于網(wǎng)頁編輯器中,這里用的是text,需要的朋友可以參考下。2010-03-03如何讓動態(tài)插入的javascript腳本代碼跑起來。
如何讓動態(tài)插入的javascript腳本代碼跑起來。...2007-01-01詳解WordPress開發(fā)中g(shù)et_current_screen()函數(shù)的使用
這篇文章主要介紹了WordPress開發(fā)中g(shù)et_current_screen()函數(shù)的使用,get_current_screen()通常在對象的實例化時使用,需要的朋友可以參考下2016-01-01