国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開(kāi)發(fā) > JS > 正文

JavaScript面向?qū)ο笾薪涌趯?shí)現(xiàn)方法詳解

2024-05-06 16:53:33
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

本文實(shí)例講述了JavaScript面向?qū)ο笾薪涌趯?shí)現(xiàn)方法。分享給大家供大家參考,具體如下:

接口是面向?qū)ο缶幊痰幕A(chǔ),它是一組包含了函數(shù)型方法的數(shù)據(jù)結(jié)構(gòu),與類一樣,都是編程語(yǔ)言中比較抽象的概念。比如生活中的接口,機(jī)頂盒,人們利用它來(lái)實(shí)現(xiàn)收看不同頻道和信號(hào)的節(jié)目,它猶如對(duì)不同類型的信息進(jìn)行集合和封裝的設(shè)備,最后把各種不同類型的信息轉(zhuǎn)換為電視能夠識(shí)別的信息。在編程語(yǔ)言中的接口,實(shí)際上是不同類的封裝并提供統(tǒng)一的外部聯(lián)系通道,這樣其他對(duì)象就可以利用接口來(lái)調(diào)用不同類的成員了。

——整理自《jQuery開(kāi)發(fā)從入門(mén)到精通》

接口的概念

構(gòu)造函數(shù)(類)是具體的實(shí)現(xiàn),接口是類的約定。API接口(應(yīng)用程序接口)、人機(jī)交互接口、電源接口、USB接口等雖然用途不同,功能各異,但是都包含一個(gè)共同的特性:約定、規(guī)范。可以說(shuō),接口就是一張契約和合同,它約定了設(shè)計(jì)者和使用者都必須遵循的要求。

接口承諾了具體類應(yīng)該事先的功能。

舉一個(gè)很有必要的例子,在java中實(shí)現(xiàn)接口,比如下面的代碼:

interface Base{ void function1(); void function2(); void function3();}

Base接口承諾了3個(gè)基本功能:function1()、function2()、function3()。這個(gè)接口就像是一份合同,在甲方(調(diào)用類的用戶)和乙方(定義類的開(kāi)發(fā)人員)之間約定。

乙方負(fù)責(zé)實(shí)現(xiàn)接口約定的功能。功能的實(shí)現(xiàn)就是所謂的類。如下實(shí)例:

class App implements Base  // 定義一個(gè)App類,用這個(gè)類來(lái)實(shí)現(xiàn)接口Base

類App將遵照接口的約定。專業(yè)來(lái)說(shuō)就是,應(yīng)用類App繼承Base接口類。

它的具體實(shí)現(xiàn)如下:

class App implements Base{ void function1(){  System.out.println("I am fun1"); } void function2(){  System.out.println("I am fun2"); } void function3(){  System.out.println("I am fun3"); }}

這樣,乙方實(shí)現(xiàn)了這個(gè)接口,而甲方也應(yīng)該來(lái)按照接口的約定去使用類App就行了。

所以說(shuō),接口(interface)和類(class),實(shí)際上都是相同的數(shù)據(jù)結(jié)構(gòu)。

在接口中可以聲明屬性,方法,事件,類型,但不能聲明變量,且不能設(shè)置被聲明成員的具體值(功能實(shí)現(xiàn))。

也就是說(shuō),接口只能定義成員,不能給定義的成員賦值。而接口作為它的繼承類或派生類的約定,繼承類或派生類共同完成接口屬性、方法、事件、類型的實(shí)現(xiàn)。在接口和實(shí)現(xiàn)類之間,不管是方法名還是屬性調(diào)用順序上都應(yīng)保持一致。

接口的目的就是約束編碼,促使代碼規(guī)范,對(duì)于強(qiáng)類型語(yǔ)言是必須的,也是非常重要的環(huán)節(jié)。但是對(duì)于JavaScript弱類型語(yǔ)言來(lái)說(shuō),嚴(yán)格的類型檢查會(huì)束縛JavaScript的靈活性。很多前端開(kāi)發(fā)人員根本不用接口,但不會(huì)影響腳本的設(shè)計(jì)。

使用接口的好處:降低對(duì)象間的耦合度,提高代碼的靈活性。學(xué)會(huì)使用接口,能夠讓手中的函數(shù)變得靈巧,這在大型開(kāi)發(fā)中是很重要的。

對(duì)于JavaScript來(lái)說(shuō),本身不支持接口功能,沒(méi)有提供內(nèi)置方法。但是人工設(shè)計(jì)一個(gè)額外的接口程序,又會(huì)對(duì)程序的性能產(chǎn)生影響。項(xiàng)目越大,這種開(kāi)銷越大。所以,用不用接口可以遵循兩個(gè)條件:

① 項(xiàng)目大小,如果是一個(gè)框架,使用接口在一定程度上會(huì)提高程序的性能。如果是簡(jiǎn)單的應(yīng)用,就不必使用接口了。

② 如果對(duì)JavaScript接口比較熟練,多用接口也可以,如果擔(dān)心過(guò)多使用接口影響性能,則可以在考慮產(chǎn)品發(fā)布前,清除接口功能模塊,或者設(shè)置接口的執(zhí)行條件。防止它被頻繁執(zhí)行,影響性能。

接口的實(shí)現(xiàn)

JavaScript中并不支持接口,但是我們可以模仿其他語(yǔ)言,來(lái)定義接口。

下面來(lái)規(guī)劃接口結(jié)構(gòu)的設(shè)計(jì)和檢測(cè)功能的實(shí)現(xiàn):

(1) 設(shè)計(jì)一個(gè)接口輔助的類結(jié)構(gòu),這個(gè)構(gòu)造函數(shù)相當(dāng)于一個(gè)過(guò)濾器,用于在接口實(shí)例化過(guò)程中,檢測(cè)初始化參數(shù)是否合法。如果符合接口設(shè)計(jì)標(biāo)準(zhǔn),則把第2個(gè)參數(shù)中每個(gè)方法名和參數(shù)個(gè)數(shù)以數(shù)組元素的形式輸入接口內(nèi)部屬性methods。在輸入前分別檢測(cè)每個(gè)參數(shù)類型是否符合規(guī)定。同時(shí)檢查參數(shù)是否存在殘缺,并即時(shí)以0補(bǔ)齊參數(shù)。

function Interface(name,methods){ // 接口輔助類,參數(shù)包括接口實(shí)例的名稱和方法集 if(arguments.length!=2){ // 如果參數(shù)個(gè)數(shù)不等于2,拋出異常。  throw new Error('標(biāo)準(zhǔn)接口約定,需要兩個(gè)參數(shù)'); } this.name = name; // 存儲(chǔ)第一個(gè)參數(shù)值,實(shí)例化后就是接口實(shí)例的名稱 this.methods = []; // 接口實(shí)例的方法存儲(chǔ)器 if(methods.length < 1){ // 如果第二個(gè)參數(shù)的元素個(gè)數(shù)為0,說(shuō)明是空數(shù)組,拋出異常。  throw new Error('接口的第二個(gè)參數(shù)不能為空'); } for(var i = 0; i < methods.length; i++){ // 開(kāi)始對(duì)第2個(gè)參數(shù)的元素進(jìn)行遍歷檢測(cè)  var item = methods[i];  if(typeof item[0] !== 'string') { // 如果第二個(gè)參數(shù)的第一個(gè)元素不是string類型,拋出異常   throw new Error("接口約定的第一個(gè)參數(shù)應(yīng)為字符串");  }  if(item[1]&&typeof item[1] !== 'number'){ // 如果第二個(gè)參數(shù)有第二個(gè)元素,且第二個(gè)元素不是number類型,拋出異常   throw new Error('接口約定的第個(gè)參數(shù)應(yīng)為數(shù)值');  }  if(item.length == 1){ // 如果第二個(gè)參數(shù)只有一個(gè)元素,那么手動(dòng)給它添加第二個(gè)元素 0   item[1] = 0;  }  this.methods.push(item); // 把符合規(guī)定的方法存儲(chǔ)到數(shù)組存儲(chǔ)器中。 }}

(2) 為接口輔助類 Interface 定義一個(gè)方法 implements,該方法將檢測(cè)實(shí)現(xiàn)類是否符合接口實(shí)例的約定。它至少包含兩個(gè)參數(shù),第1個(gè)參數(shù)o表示實(shí)現(xiàn)類,第2個(gè)參數(shù)及其后面的參數(shù)表示該類將要實(shí)現(xiàn)的接口標(biāo)準(zhǔn)。也就是說(shuō),可以為一個(gè)類指定多個(gè)接口約定,這樣就可以更靈活的分類設(shè)計(jì)接口實(shí)例。然后遍歷第二個(gè)及其后面的所有參數(shù),在循環(huán)結(jié)構(gòu)中,先潔廁接口是否為接口標(biāo)準(zhǔn)的實(shí)例,否則就會(huì)拋出異常。再?gòu)慕涌趯?shí)例的方法存儲(chǔ)器中逐一讀取方法名,填入類中來(lái)驗(yàn)證類的方法是否符合接口實(shí)例設(shè)置的標(biāo)準(zhǔn),驗(yàn)證包括方法名、function類型和參數(shù)個(gè)數(shù)。如果有問(wèn)題,立即拋出異常。

Interface.implements = function(o){ // 用于檢測(cè)類方法是否符合接口實(shí)例的約定 ,此處的o,將來(lái)會(huì)是類中的this if(arguments.length<2){ // 檢測(cè)該方法傳遞的數(shù)值是否符合規(guī)定  throw new Error("接口約定類應(yīng)包含至少兩個(gè)參數(shù)。"); } for(var i=1;i<arguments.length; i++){ // 遍歷檢測(cè)類所遵循的實(shí)例是否合法  var interface = arguments[i]; // 這里interface表示接口的實(shí)例對(duì)象。  if(interface.constructor !== Interface){   throw new Error('從第2個(gè)以上的參數(shù)必須為接口實(shí)例');  }  for(var j=0;j<interface.methods.length;j++){ // 檢測(cè)類方法是否符合接口實(shí)例的約定   var method = interface.methods[j][0];   if(!o[method] || typeof o[method] !== 'function' || o[method].length!==interface.methods[j][1]) {    throw new Error("該實(shí)現(xiàn)類沒(méi)能履行" + interface.name + "接口方法" + method + "約定");   }  } }}

(3) 實(shí)例化接口標(biāo)準(zhǔn),Interface 接口僅僅是個(gè)構(gòu)造函數(shù),也就是個(gè)框架協(xié)議,還沒(méi)有制定類應(yīng)該遵循的具體標(biāo)準(zhǔn)。框架協(xié)議中,已經(jīng)設(shè)計(jì)好了監(jiān)測(cè)邏輯,一旦實(shí)例化接口,并指明類應(yīng)遵守的約定,那么應(yīng)用該標(biāo)準(zhǔn)的實(shí)例的類就必須準(zhǔn)守。下面根據(jù)Interface接口標(biāo)準(zhǔn)定義了6個(gè)具體的接口實(shí)例。

// 設(shè)置接口的不同實(shí)現(xiàn)實(shí)例var Get = new Interface("Get",[["get",0]]);var Set = new Interface("Set",[["set",1]]);var Saying = new Interface("Saying",[["saying",1]]);var Base = new Interface("Base",[["get",0],["set",1]]);var Base1 = new Interface("Base1",[["set",1],["get",0]]);var Base2 = new Interface("Base2",[["get",0],["set",1],["saying",1]]);

(4) 在類中定義應(yīng)該實(shí)現(xiàn)的標(biāo)準(zhǔn),即類應(yīng)該遵循的接口約定。

// 創(chuàng)建一個(gè)木驢類function Neddy(){ this.name = ''; Interface.implements(this,Base,Get,Set); // 讓木驢類實(shí)現(xiàn)接口的實(shí)例,可以指定多個(gè),也可以只有一個(gè)。}// 按照接口實(shí)例來(lái)定義 兩個(gè)方法get,setNeddy.prototype.get = function(){ return this.name;}Neddy.prototype.set = function(name){ this.name = name;}

(5) 在類中設(shè)置了多個(gè)接口實(shí)例,我們來(lái)進(jìn)行檢測(cè)

// 檢測(cè)接口實(shí)現(xiàn)var neddy = new Neddy();neddy.set("Testing");console.log(neddy.get()); // Testing

成功完成接口的應(yīng)用,這里,如果在Neddy類中,我們讓它實(shí)現(xiàn)的接口實(shí)例和 Neddy.prototype中給類定義的方法不統(tǒng)一,或者接口與接口之間有沖突,就會(huì)拋出異常。比如我們可以修改Neddy中的接口實(shí)現(xiàn),再給它添加一個(gè)接口實(shí)例Base2,就會(huì)報(bào)異常,因?yàn)槲覀儧](méi)有按照接口的協(xié)議,給Neddy添加saying()方法。

上面的舉例只是用js來(lái)模擬實(shí)現(xiàn)接口功能,在實(shí)際開(kāi)發(fā)中,我們需要根據(jù)不同的需求,開(kāi)發(fā)不同的接口。

擴(kuò)展知識(shí) :

檢測(cè)函數(shù)的參數(shù)列表一般有三種形式

  • ① arguments.callee.length
  • ② 函數(shù)名.length
  • ③ arguments.length

其中 ① 和 ② 是一樣的,③ 視具體情況而定。
一般函數(shù)聲明式的定義有個(gè)默認(rèn)屬性name繼承自O(shè)bject ,舉例如下:

function fn(x,y){  console.log(fn.name); // fn  console.log(arguments.callee.name); // fn  console.log(fn.length); // 2  console.log(arguments.callee.length); // 2  console.log(arguments.length); // 視具體情況而定}fn(1,2,3); // 分別輸出 fn fn 2 2 3

為了說(shuō)明上面接口檢測(cè)參數(shù)長(zhǎng)度 o[method].length  的問(wèn)題 ,舉例如下:

function A(){}A.prototype.say = function (x,y,z,o) {}var a = new A();console.log(a['say'].length); // 4

希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到JavaScript/Ajax教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 桓仁| 汶上县| 都昌县| 澎湖县| 博野县| 丰顺县| 平阳县| 普格县| 惠水县| 丽水市| 昆山市| 临泉县| 禄丰县| 花莲市| 吴忠市| 盘锦市| 宿州市| 涿州市| 沙田区| 黄龙县| 孝昌县| 上杭县| 安国市| 淳化县| 安乡县| 息烽县| 大田县| 凌源市| 通化市| 东阳市| 城市| 沭阳县| 满城县| 和硕县| 扎兰屯市| 长汀县| 四会市| 来安县| 木里| 温州市| 通江县|