javascript面向?qū)ο笕筇卣髦庋b實(shí)例詳解
本文實(shí)例講述了javascript面向?qū)ο笕筇卣髦庋b。分享給大家供大家參考,具體如下:
封裝
封裝(Encapsulation):就是把對象內(nèi)部數(shù)據(jù)和操作細(xì)節(jié)進(jìn)行隱藏。很多面向?qū)ο笳Z言都支持封裝特性,提供關(guān)鍵字如private來隱藏某些屬性和方法。要想訪問被封裝對象中的數(shù)據(jù),只能使用對象專門提供的對外接口,這個接口一般為方法。調(diào)用該方法能夠獲取對象內(nèi)部數(shù)據(jù)。
在JavaScript語言中沒有提供專門的信息封裝關(guān)鍵字,不過可以使用閉包來創(chuàng)建,只允許從對象內(nèi)部訪問的方法和屬性。另外,接口也是數(shù)據(jù)封裝的一種工具,接口提供了外界訪問方法的約定。在應(yīng)用開發(fā)中,所有類都應(yīng)定義接口,類只向外提供已實(shí)現(xiàn)接口中規(guī)定的方法,任何別的方法都是隱藏的。其所有屬性都是私有的,外界只能通過接口中定義的存取操作與之打交道。
---引自 《jQuery開發(fā)從入門到精通》,不過原書有錯誤,或者可能是我錯買了盜版,不過下面代碼都是經(jīng)過我修改的,沒有問題。
被動封裝
被動封裝:就是對對象內(nèi)部數(shù)據(jù)進(jìn)行適當(dāng)約定,這種約定具有很強(qiáng)的主觀性,沒有強(qiáng)制性保證,主要針對公共對象而言。一般來說,JavaScript所包含的數(shù)據(jù)都是公開的,沒有隱私可言,其中的信息可以隨意被訪問。下面給出一個例子來闡述:
var Person = function (name,gender) { if(name === undefined) { throw new Error("name is necessary") } else { this.name = name; } if(gender === undefined) { throw new Error("gender is necessary") } else { this.gender = gender; } } var p = new Person("Tom",1); // 如果我們實(shí)例化的時候,如果傳遞參數(shù)錯誤了,將會報異常
為了數(shù)據(jù)安全,代碼中適當(dāng)?shù)脑黾恿艘恍l件限制,避免非法信息侵入。
var Animal = function (species) { if(!this.checkSpecies(species)) { throw new Error('species is illegal'); } else { this.species = species; } } Animal.prototype = { checkSpecies:function(species){ // 檢測 species , 參數(shù)為 species , 合法返回true ,這里可自定義檢測邏輯 // 這里先讓它直接返回 true return true; } } var ani = new Animal("dog");
從更安全和擴(kuò)展的角度來說,凡是類都應(yīng)該定義接口,這樣能夠保證數(shù)據(jù)存取更加安全,同時也方便團(tuán)隊(duì)的合作。內(nèi)部私有方法檢測和接口措施可在一定程度上保護(hù)對象內(nèi)部數(shù)據(jù),但是他們也存在一個致命漏洞(這些屬性和方法可以被公開重置,面對公開覆蓋屬性和方法值,任何人都無法阻止這種行為。),比如這樣的:
var Util = function() {}; Util.prototype = { _say:function(){ console.log("這里有一個私有的成員 _say方法"); } } // 下面我們來修改它 Util.prototype._say = function(){ console.log('哈哈,我已經(jīng)被修改了'); } // 開始檢測 var util = new Util; util._say(); // 哈哈,我已經(jīng)被修改了
同時內(nèi)部檢測和接口可以在一定程度上占用了系統(tǒng)開銷,這個問題也是必須認(rèn)真考慮的。
就像上面的代碼那樣,一般我們約定了區(qū)別公共和私有成員,就是在一些方法和屬性名稱前或者后加下劃線,來表示私有。
下劃線命名是一種約定俗稱的命名規(guī)范,表示一個屬性和方法僅供內(nèi)部使用,直接訪問可能會導(dǎo)致意外發(fā)生。
以上數(shù)據(jù)保護(hù)方式都是被動性防御,因?yàn)樗麄冎皇且环N約定,只有在遵守的時候才有效果。主要適用于非敏感性的內(nèi)部方法和屬性。
主動封裝
在js中,因?yàn)楹瘮?shù)有作用域,在函數(shù)內(nèi)部聲明的變量,在函數(shù)外部無法訪問。而所以的私有和公有的區(qū)別就在于在對象外部是否可以訪問。所以實(shí)現(xiàn)封裝的最佳選擇是使用函數(shù)的作用域。舉例:
function haha() { var n = 1; function hehe() { n++; } hehe(); return n; } console.log(haha()); // 2
函數(shù)haha內(nèi)部有私有變量n,在此作用域中,hehe能夠訪問n,而haha外部的任何函數(shù)都無法訪問haha里的n。
同樣的,我們在函數(shù)內(nèi)部返回hehe,就可以在外部來調(diào)用haha私有函數(shù)hehe。
function haha() { var n = 1; function hehe() { return ++n; } return hehe; } console.log(haha()()); // 2
函數(shù)作用域內(nèi)部的方法無法被外界訪問,但是在函數(shù)作用域內(nèi)部的其他公共方法可以訪問到它們,于是利用公共方法為中轉(zhuǎn)站,可以巧妙的把內(nèi)部私有方法公開化。因此這些公共方法也被稱為特權(quán)方法,即在方法前面加this關(guān)鍵字。
使用這種方式創(chuàng)建的對象具有真正的封裝性如:
function A() { // 私有方法 _xx function _xx(){} // 公有方法 this.xx = function() { return _xx; } } A.prototype = { other:function() { console.log("other方法代表不需要訪問私有屬性和方法的方法,一般放在原型里"); } }
但是這種方式也有一些缺點(diǎn):
① 新生成的每個實(shí)例對象都會拷貝構(gòu)造函數(shù)中的屬性和方法,而私有的_xx 無疑在每次實(shí)例化的時候都會重復(fù)拷貝,這樣會占用大量內(nèi)存,所以不適合大量使用,僅在必要時適當(dāng)使用
② 不利于類的繼承,所有派生的子類都不能訪問超類中的私有屬性和方法。不過可以使用特權(quán)方法來訪問超類中的私有屬性和方法。舉個例子:
// B 是超類 function B() { var _private = 1; function _checkPrivate() { return _private; } this.checkPrivate = function() { return _checkPrivate; } } // C 是派生類 function C() { B.call(this); // 用call 實(shí)現(xiàn)繼承 ,后面我們會講到如何繼承 // this.private = _private; // 這里嘗試訪問超類的私有屬性,因?yàn)闊o法訪問,會報錯 } // 實(shí)例化 派生類C var c = new C(); // console.log(c.private); // 和在C內(nèi)部的嘗試一樣,是無法訪問的,報錯 // 不過可以用下面的方法訪問超類中的私有屬性 console.log(c.checkPrivate()()); // 1
靜態(tài)方法
在面向?qū)ο缶幊讨校蠖鄶?shù)的方法和屬性與類的實(shí)例產(chǎn)生聯(lián)系。還有一種情況是,靜態(tài)屬性和方法是與類本身直接聯(lián)系,可直接從類訪問,也就是說,靜態(tài)成員在類上操作,而不是實(shí)例上。在JavaScript中的Math和Global都是靜態(tài)對象,不需要實(shí)例化就可直接訪問。
類的靜態(tài)成員,包括私有和公共兩種。他們在系統(tǒng)中只有一份副本,意思就是說他們不會被分成多份傳遞給不同的實(shí)例對象。而是通過函數(shù)指針進(jìn)行引用。書上有個例子非常好,下面舉例:
var F = (function(){ // 把閉包函數(shù)賦給F,返回一個構(gòu)造函數(shù) var _a = 1; // 定義一個閉包體內(nèi)的私有變量 this.a = _a; // 閉包體內(nèi)的公共屬性 a this.get1 = function(){ // 閉包體內(nèi)的公共方法get1 return _a; } this.set1 = function(x){ // 閉包體內(nèi)的公共方法set1 _a = x; }; return function(){ // 返回一個構(gòu)造函數(shù),構(gòu)造函數(shù)也是函數(shù),更是對象(相當(dāng)于一個類) this.get2 = function() { // 類的get2方法 return _a; }; this.set2 = function(x) { // 類的set2方法 _a = x; }; } })(); // 定義類的靜態(tài)公共方法和屬性 F.get3 = function(){ // 定義一個靜態(tài)方法get3 return get1(); // 這里可以直接使用 F內(nèi)的公共方法get1 } F.set3 = function(x) { // 定義一個靜態(tài)方法set3 return set1(x); // 同get1 } // 下面開始測試 var f = new F(); // 實(shí)例化這個類 console.log(f.get2()); // 1 用實(shí)例對象訪問公共方法get2 F.set3(3); // 調(diào)用靜態(tài)方法set3 console.log(F.get3()); // 3 F.A = ++a; // 定義一個靜態(tài)屬性A console.log(F.A); // 2
我們推薦使用這種閉包的封裝方式
感興趣的朋友可以使用在線HTML/CSS/JavaScript代碼運(yùn)行工具:http://tools.jb51.net/code/HtmlJsRun測試上述代碼運(yùn)行效果。
更多關(guān)于JavaScript相關(guān)內(nèi)容可查看本站專題:《javascript面向?qū)ο笕腴T教程》、《JavaScript錯誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》
希望本文所述對大家JavaScript程序設(shè)計(jì)有所幫助。
- 學(xué)習(xí)Javascript面向?qū)ο缶幊讨庋b
- Javascript 面向?qū)ο缶幊蹋ㄒ唬?封裝
- javascript 面向?qū)ο缶幊袒A(chǔ):封裝
- Javascript之面向?qū)ο?-封裝
- js實(shí)現(xiàn)對ajax請求面向?qū)ο蟮姆庋b
- javascript 面向?qū)ο蠓庋b與繼承
- javascript面向?qū)ο蟀b類Class封裝類庫剖析
- Javascript 面向?qū)ο螅ǘ┓庋b代碼
- 面向?qū)ο蟮腏avascript之三(封裝和信息隱藏)
- javascript對XMLHttpRequest異步請求的面向?qū)ο蠓庋b
- javascript 面向?qū)ο笕吕砭氈當(dāng)?shù)據(jù)的封裝
- JS面向?qū)ο缶幊袒A(chǔ)篇(二) 封裝操作實(shí)例詳解
相關(guān)文章
前端實(shí)現(xiàn)瀏覽器自定義滾動條寫法實(shí)例
自定義滾動條最早是IE玩出來的,但是后來,不知道為什么IE把這個有意思的功能廢棄了,下面這篇文章主要給大家介紹了關(guān)于前端實(shí)現(xiàn)瀏覽器自定義滾動條寫法的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-06-06JS實(shí)現(xiàn)復(fù)制內(nèi)容到剪貼板功能
本文主要介紹了JS實(shí)現(xiàn)復(fù)制內(nèi)容到剪貼板功能的步驟方法,可兼容所有PC瀏覽器,不兼容手機(jī)端。具有一定的參考價值,下面跟著小編一起來看下吧2017-02-02JS+CSS實(shí)現(xiàn)淡入式焦點(diǎn)圖片幻燈切換效果的方法
這篇文章主要介紹了JS+CSS實(shí)現(xiàn)淡入式焦點(diǎn)圖片幻燈切換效果的方法,實(shí)例分析了javascript操作圖片、css等元素實(shí)現(xiàn)幻燈片的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-02-02微信小程序?qū)崿F(xiàn)彈出輸入框代碼實(shí)例
最近在寫一個微信小程序,有一個需求是點(diǎn)擊一個按鈕后,出現(xiàn)一個輸入框,然后根據(jù)用戶的輸入再進(jìn)行操作,所以這篇文章主要給大家介紹了關(guān)于微信小程序?qū)崿F(xiàn)彈出輸入框的相關(guān)資料,需要的朋友可以參考下2023-09-09prototype.js簡單實(shí)現(xiàn)ajax功能示例
這篇文章主要介紹了prototype.js簡單實(shí)現(xiàn)ajax功能,結(jié)合實(shí)例形式分析了prototype.js前臺實(shí)現(xiàn)ajax與后臺struts的相關(guān)操作技巧,需要的朋友可以參考下2017-10-10使用JavaScript 實(shí)現(xiàn)的人臉檢測
這篇文章主要介紹了使用JavaScript 實(shí)現(xiàn)的人臉檢測的方法和實(shí)例,非常的不錯,這里推薦給大家,有需要的小伙伴參考下。2015-03-03