本文實例講述了JavaScript面向?qū)ο笾薪涌趯崿F(xiàn)方法。分享給大家供大家參考,具體如下:
我們提供的服務(wù)有:成都做網(wǎng)站、成都網(wǎng)站建設(shè)、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、蘭溪ssl等。為近千家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的蘭溪網(wǎng)站制作公司
接口是面向?qū)ο缶幊痰幕A(chǔ),它是一組包含了函數(shù)型方法的數(shù)據(jù)結(jié)構(gòu),與類一樣,都是編程語言中比較抽象的概念。比如生活中的接口,機頂盒,人們利用它來實現(xiàn)收看不同頻道和信號的節(jié)目,它猶如對不同類型的信息進行集合和封裝的設(shè)備,最后把各種不同類型的信息轉(zhuǎn)換為電視能夠識別的信息。在編程語言中的接口,實際上是不同類的封裝并提供統(tǒng)一的外部聯(lián)系通道,這樣其他對象就可以利用接口來調(diào)用不同類的成員了。
——整理自《jQuery開發(fā)從入門到精通》
接口的概念
構(gòu)造函數(shù)(類)是具體的實現(xiàn),接口是類的約定。API接口(應(yīng)用程序接口)、人機交互接口、電源接口、USB接口等雖然用途不同,功能各異,但是都包含一個共同的特性:約定、規(guī)范??梢哉f,接口就是一張契約和合同,它約定了設(shè)計者和使用者都必須遵循的要求。
接口承諾了具體類應(yīng)該事先的功能。
舉一個很有必要的例子,在java中實現(xiàn)接口,比如下面的代碼:
interface Base{ void function1(); void function2(); void function3(); }
Base接口承諾了3個基本功能:function1()、function2()、function3()。這個接口就像是一份合同,在甲方(調(diào)用類的用戶)和乙方(定義類的開發(fā)人員)之間約定。
乙方負(fù)責(zé)實現(xiàn)接口約定的功能。功能的實現(xiàn)就是所謂的類。如下實例:
class App implements Base // 定義一個App類,用這個類來實現(xiàn)接口Base
類App將遵照接口的約定。專業(yè)來說就是,應(yīng)用類App繼承Base接口類。
它的具體實現(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"); } }
這樣,乙方實現(xiàn)了這個接口,而甲方也應(yīng)該來按照接口的約定去使用類App就行了。
所以說,接口(interface)和類(class),實際上都是相同的數(shù)據(jù)結(jié)構(gòu)。
在接口中可以聲明屬性,方法,事件,類型,但不能聲明變量,且不能設(shè)置被聲明成員的具體值(功能實現(xiàn))。
也就是說,接口只能定義成員,不能給定義的成員賦值。而接口作為它的繼承類或派生類的約定,繼承類或派生類共同完成接口屬性、方法、事件、類型的實現(xiàn)。在接口和實現(xiàn)類之間,不管是方法名還是屬性調(diào)用順序上都應(yīng)保持一致。
接口的目的就是約束編碼,促使代碼規(guī)范,對于強類型語言是必須的,也是非常重要的環(huán)節(jié)。但是對于JavaScript弱類型語言來說,嚴(yán)格的類型檢查會束縛JavaScript的靈活性。很多前端開發(fā)人員根本不用接口,但不會影響腳本的設(shè)計。
使用接口的好處:降低對象間的耦合度,提高代碼的靈活性。學(xué)會使用接口,能夠讓手中的函數(shù)變得靈巧,這在大型開發(fā)中是很重要的。
對于JavaScript來說,本身不支持接口功能,沒有提供內(nèi)置方法。但是人工設(shè)計一個額外的接口程序,又會對程序的性能產(chǎn)生影響。項目越大,這種開銷越大。所以,用不用接口可以遵循兩個條件:
① 項目大小,如果是一個框架,使用接口在一定程度上會提高程序的性能。如果是簡單的應(yīng)用,就不必使用接口了。
② 如果對JavaScript接口比較熟練,多用接口也可以,如果擔(dān)心過多使用接口影響性能,則可以在考慮產(chǎn)品發(fā)布前,清除接口功能模塊,或者設(shè)置接口的執(zhí)行條件。防止它被頻繁執(zhí)行,影響性能。
接口的實現(xiàn)
JavaScript中并不支持接口,但是我們可以模仿其他語言,來定義接口。
下面來規(guī)劃接口結(jié)構(gòu)的設(shè)計和檢測功能的實現(xiàn):
(1) 設(shè)計一個接口輔助的類結(jié)構(gòu),這個構(gòu)造函數(shù)相當(dāng)于一個過濾器,用于在接口實例化過程中,檢測初始化參數(shù)是否合法。如果符合接口設(shè)計標(biāo)準(zhǔn),則把第2個參數(shù)中每個方法名和參數(shù)個數(shù)以數(shù)組元素的形式輸入接口內(nèi)部屬性methods。在輸入前分別檢測每個參數(shù)類型是否符合規(guī)定。同時檢查參數(shù)是否存在殘缺,并即時以0補齊參數(shù)。
function Interface(name,methods){ // 接口輔助類,參數(shù)包括接口實例的名稱和方法集 if(arguments.length!=2){ // 如果參數(shù)個數(shù)不等于2,拋出異常。 throw new Error('標(biāo)準(zhǔn)接口約定,需要兩個參數(shù)'); } this.name = name; // 存儲第一個參數(shù)值,實例化后就是接口實例的名稱 this.methods = []; // 接口實例的方法存儲器 if(methods.length < 1){ // 如果第二個參數(shù)的元素個數(shù)為0,說明是空數(shù)組,拋出異常。 throw new Error('接口的第二個參數(shù)不能為空'); } for(var i = 0; i < methods.length; i++){ // 開始對第2個參數(shù)的元素進行遍歷檢測 var item = methods[i]; if(typeof item[0] !== 'string') { // 如果第二個參數(shù)的第一個元素不是string類型,拋出異常 throw new Error("接口約定的第一個參數(shù)應(yīng)為字符串"); } if(item[1]&&typeof item[1] !== 'number'){ // 如果第二個參數(shù)有第二個元素,且第二個元素不是number類型,拋出異常 throw new Error('接口約定的第個參數(shù)應(yīng)為數(shù)值'); } if(item.length == 1){ // 如果第二個參數(shù)只有一個元素,那么手動給它添加第二個元素 0 item[1] = 0; } this.methods.push(item); // 把符合規(guī)定的方法存儲到數(shù)組存儲器中。 } }
(2) 為接口輔助類 Interface 定義一個方法 implements,該方法將檢測實現(xiàn)類是否符合接口實例的約定。它至少包含兩個參數(shù),第1個參數(shù)o表示實現(xiàn)類,第2個參數(shù)及其后面的參數(shù)表示該類將要實現(xiàn)的接口標(biāo)準(zhǔn)。也就是說,可以為一個類指定多個接口約定,這樣就可以更靈活的分類設(shè)計接口實例。然后遍歷第二個及其后面的所有參數(shù),在循環(huán)結(jié)構(gòu)中,先潔廁接口是否為接口標(biāo)準(zhǔn)的實例,否則就會拋出異常。再從接口實例的方法存儲器中逐一讀取方法名,填入類中來驗證類的方法是否符合接口實例設(shè)置的標(biāo)準(zhǔn),驗證包括方法名、function類型和參數(shù)個數(shù)。如果有問題,立即拋出異常。
Interface.implements = function(o){ // 用于檢測類方法是否符合接口實例的約定 ,此處的o,將來會是類中的this if(arguments.length<2){ // 檢測該方法傳遞的數(shù)值是否符合規(guī)定 throw new Error("接口約定類應(yīng)包含至少兩個參數(shù)。"); } for(var i=1;i
(3) 實例化接口標(biāo)準(zhǔn),Interface 接口僅僅是個構(gòu)造函數(shù),也就是個框架協(xié)議,還沒有制定類應(yīng)該遵循的具體標(biāo)準(zhǔn)??蚣軈f(xié)議中,已經(jīng)設(shè)計好了監(jiān)測邏輯,一旦實例化接口,并指明類應(yīng)遵守的約定,那么應(yīng)用該標(biāo)準(zhǔn)的實例的類就必須準(zhǔn)守。下面根據(jù)Interface接口標(biāo)準(zhǔn)定義了6個具體的接口實例。
// 設(shè)置接口的不同實現(xiàn)實例 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)該實現(xiàn)的標(biāo)準(zhǔn),即類應(yīng)該遵循的接口約定。
// 創(chuàng)建一個木驢類 function Neddy(){ this.name = ''; Interface.implements(this,Base,Get,Set); // 讓木驢類實現(xiàn)接口的實例,可以指定多個,也可以只有一個。 } // 按照接口實例來定義 兩個方法get,set Neddy.prototype.get = function(){ return this.name; } Neddy.prototype.set = function(name){ this.name = name; }
(5) 在類中設(shè)置了多個接口實例,我們來進行檢測
// 檢測接口實現(xiàn) var neddy = new Neddy(); neddy.set("Testing"); console.log(neddy.get()); // Testing
成功完成接口的應(yīng)用,這里,如果在Neddy類中,我們讓它實現(xiàn)的接口實例和 Neddy.prototype
中給類定義的方法不統(tǒng)一,或者接口與接口之間有沖突,就會拋出異常。比如我們可以修改Neddy中的接口實現(xiàn),再給它添加一個接口實例Base2,就會報異常,因為我們沒有按照接口的協(xié)議,給Neddy添加saying()方法。
上面的舉例只是用js來模擬實現(xiàn)接口功能,在實際開發(fā)中,我們需要根據(jù)不同的需求,開發(fā)不同的接口。
擴展知識 :
檢測函數(shù)的參數(shù)列表一般有三種形式
其中 ① 和 ② 是一樣的,③ 視具體情況而定。
一般函數(shù)聲明式的定義有個默認(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
為了說明上面接口檢測參數(shù)長度 o[method].length
的問題 ,舉例如下:
function A(){} A.prototype.say = function (x,y,z,o) {} var a = new A(); console.log(a['say'].length); // 4
更多關(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é)運算用法總結(jié)》
希望本文所述對大家JavaScript程序設(shè)計有所幫助。