javascript
深入理解JavaScript模拟私有成员
一般的面向?qū)ο笳Z言C++或JAVA,對象都是有私有成員的。js中沒有類的改變,同樣也沒有對象的私有成員這個概念。但是可以通過某些特殊寫法,模擬出私有成員。
1、特權(quán)模式:
(1)在構(gòu)造函數(shù)內(nèi)部聲明的變量、子函數(shù)以及參數(shù),全部都是函數(shù)私有的,可以看作私有成員。給this指針添加的閉包,全部都是公有成員。
所以下面例子:參數(shù)a/b、變量_value、函數(shù)add是私有的,外面無法訪問,故c1.add會報錯
setValue和getValue是公有的,c1可以訪問
function MyClass(a,b){ //private var _value=0; function add(){ _value=a+b; } //process add(); //public this.getValue=function(){ return _value; } this.setValue=function(a1,b1){ a=a1; b=b1; add(); } } var c1=new MyClass(1,2); var c2=new MyClass(1,2); c1.setValue(3,4); alert(c1.getValue());//7 alert(c2.getValue());//3 alert(c1.add());//c1中無add方法,報錯c1.add is not a function(…) (2)這種模擬方法的優(yōu)點是代碼清晰明了,缺點是每個對象的成員函數(shù),不論是私有還是公有,都是自己獨有的。即便成員函數(shù)的功能相同,但他們卻是存放在不同位置的不同函數(shù)。
(3)這種模擬方法只模仿了一個外形。OOP語言中,每個對象的成員函數(shù),在內(nèi)存中只體現(xiàn)為一個單元,我們違背了這一原則。
2、私有作用域模式:
(1)既然模擬出了塊級作用域,可以考慮把塊級作用域拿來,模擬一下私有成員。
(function(){ //private var _value=0, _a=0, _b=0; function add(){ _value=_a+_b; }//construct MyClass=function(a,b){ _a=a; _b=b; add(); } //public MyClass.prototype.getValue=function(){ return _value; } MyClass.prototype.setValue=function(a1,b1){ _a=a1; _b=b1; add(); } })(); var c1=new MyClass(1,2); var c2=new MyClass(1,2); c1.setValue(3,4); alert(c1.getValue());//7 alert(c2.getValue());//7 alert(c1.add());//報錯 (2)上面例子我們使用了塊級作用域,_value、_a、_b、add都是匿名函數(shù)的私有變量;MyClass前面沒有var,所有MyClass是全局變量,可以在塊級作用域外部使用;getValue和setValue是通過原型模式為MyClass添加的公共方法。
(3)這樣寫,MyClass所有實例的公共方法不再單獨創(chuàng)建,而是共享使用;而私有方法,則是共享作用域鏈中的add,也不是獨立創(chuàng)建的。針對成員方法而言,已經(jīng)與C++和java非常接近了。
(4)但這樣寫的缺點也是顯而易見的,就是私有數(shù)據(jù)成員_value、_a、_b在各實例之間也是共享的。這些成員,相當(dāng)于static成員。
3、綜合模式
(function(){ //private static var _count=0; function add(a,b){ return a+b; } //construct MyClass=function(a,b){ //private var _data={ value:0 } //process _data.value=add(a,b); _count++; //public this.data=function(){return _data;} } //public MyClass.prototype.getValue=function(){ return this.data().value; } MyClass.prototype.setValue=function(a,b){ this.data().value=add(a,b); } MyClass.prototype.getCount=function(){ return _count; } })(); var c1=new MyClass(1,2); var c2=new MyClass(1,2); c1.setValue(3,4); alert(c1.getValue());//7 alert(c2.getValue());//3 alert(c1.getCount());//2 alert(c2.getCount());//2 (1)為了解決私有作用域模式中私有數(shù)據(jù)成員共享的問題,必須將私有數(shù)據(jù)成員寫在MyClass內(nèi)。但這樣,公有成員函數(shù)就不能使用他們了。所以還是要使用一個特權(quán)函數(shù),提供私有數(shù)據(jù)成員的接口,這個是無法避免的,因此只能讓代價盡量的小,比如對私有數(shù)據(jù)成員做一個打包。
(2)私有方法是內(nèi)存共享的,比如add函數(shù)。然而實際上,私有方法只要共享內(nèi)存,就是private static狀態(tài),而private static狀態(tài)方法,如果想使用非形參變量時,也只能使用private static的變量,比如_count。想使用實例的私有數(shù)據(jù)成員,只能通過形參傳入。
(3)公有方法是內(nèi)存共享的,是通過原型鏈實現(xiàn)的。公有方法使用私有數(shù)據(jù)成員,就必須得到私有數(shù)據(jù)成員的接口。我們做的this.data就是接口。
(4)整個模式中,閉包個數(shù)只有一個,就是this.data,這個閉包是無法避免的。
總結(jié)
以上是生活随笔為你收集整理的深入理解JavaScript模拟私有成员的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows7环境下使用pip安装My
- 下一篇: C#跑马灯,图片滚动,后台获取图片地址。