JavaScript面向?qū)ο蟮闹С衷趺磳?shí)現(xiàn)-創(chuàng)新互聯(lián)

本篇內(nèi)容介紹了“JavaScript面向?qū)ο蟮闹С衷趺磳?shí)現(xiàn)”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

成都創(chuàng)新互聯(lián)主打移動(dòng)網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、外貿(mào)營(yíng)銷(xiāo)網(wǎng)站建設(shè)、網(wǎng)站改版、網(wǎng)絡(luò)推廣、網(wǎng)站維護(hù)、域名注冊(cè)、等互聯(lián)網(wǎng)信息服務(wù),為各行業(yè)提供服務(wù)。在技術(shù)實(shí)力的保障下,我們?yōu)榭蛻舫兄Z穩(wěn)定,放心的服務(wù),根據(jù)網(wǎng)站的內(nèi)容與功能再?zèng)Q定采用什么樣的設(shè)計(jì)。最后,要實(shí)現(xiàn)符合網(wǎng)站需求的內(nèi)容、功能與設(shè)計(jì),我們還會(huì)規(guī)劃穩(wěn)定安全的技術(shù)方案做保障。

在JavaScript中,我們需要通過(guò)一個(gè)函數(shù)來(lái)聲明自己的object類(lèi)型:
//---------------------------------------------------------
// JavaScript中對(duì)象的類(lèi)型聲明的形式代碼
// (以后的文檔中,“對(duì)象名”通常用MyObject來(lái)替代)
//---------------------------------------------------------
function 對(duì)象名(參數(shù)表) {
 this.屬性 = 初始值;

 this.方法 = function(方法參數(shù)表) {
   // 方法實(shí)現(xiàn)代碼
 }
}

然后,我們可以通過(guò)這樣的代碼來(lái)創(chuàng)建這個(gè)對(duì)象類(lèi)型的一個(gè)實(shí)例:
//---------------------------------------------------------
// 創(chuàng)建實(shí)例的形式代碼
// (以后的文檔中,“實(shí)例變量名”通常用obj來(lái)替代)
//---------------------------------------------------------
var 實(shí)例變量名 = new 對(duì)象名(參數(shù)表);

接下來(lái)我們來(lái)看“對(duì)象”在JavaScript中的一些具體實(shí)現(xiàn)和奇怪特性。

1). 函數(shù)在JavaScript的面向?qū)ο髾C(jī)制中的五重身份
------
“對(duì)象名”??如MyObject()??這個(gè)函數(shù)充當(dāng)了以下語(yǔ)言角色:
 (1) 普通函數(shù)
 (2) 類(lèi)型聲明
 (3) 類(lèi)型的實(shí)現(xiàn)
 (4) 類(lèi)引用
 (5) 對(duì)象的構(gòu)造函數(shù)

一些程序員(例如Delphi程序員)習(xí)慣于類(lèi)型聲明與實(shí)現(xiàn)分開(kāi)。例如在delphi中,Interface節(jié)用于聲明類(lèi)型或者變量,而implementation節(jié)用于書(shū)寫(xiě)類(lèi)型的實(shí)現(xiàn)代碼,或者一些用于執(zhí)行的函數(shù)、代碼流程。

但在JavaScript中,類(lèi)型的聲明與實(shí)現(xiàn)是混在一起的。一個(gè)對(duì)象的類(lèi)型(類(lèi))通過(guò)函數(shù)來(lái)聲明,this.xxxx表明了該對(duì)象可具有的屬性或者方法。

這個(gè)函數(shù)的同時(shí)也是“類(lèi)引用”。在JavaScript,如果你需要識(shí)別一個(gè)對(duì)象的具體型別,你需要執(zhí)有一個(gè)“類(lèi)引用”。??當(dāng)然,也就是這個(gè)函數(shù)的名字。instanceof 運(yùn)算符就用于識(shí)別實(shí)例的類(lèi)型,我們來(lái)看一下它的應(yīng)用:
//---------------------------------------------------------
// JavaScript中對(duì)象的類(lèi)型識(shí)別
//   語(yǔ)法:  對(duì)象實(shí)例 instanceof 類(lèi)引用
//---------------------------------------------------------
function MyObject() {
 this.data = 'test data';
}

// 這里MyObject()作為構(gòu)造函數(shù)使用
var obj = new MyObject();
var arr = new Array();

// 這里MyObject作為類(lèi)引用使用
document.writeln(obj instanceof MyObject);
document.writeln(arr instanceof MyObject);

2). 反射機(jī)制在JavaScript中的實(shí)現(xiàn)
------
 JavaScript中通過(guò)for..in語(yǔ)法來(lái)實(shí)現(xiàn)了反射機(jī)制。但是JavaScript中并不明確區(qū)分“屬性”與“方法”,以及“事件”。因此,對(duì)屬性的類(lèi)型考查在JS中是個(gè)問(wèn)題。下面的代碼簡(jiǎn)單示例for..in的使用與屬性識(shí)別:
//---------------------------------------------------------
// JavaScript中for..in的使用和屬性識(shí)別
//---------------------------------------------------------
var _r_event = _r_event = /^[Oo]n.*/;
var colorSetting = {
 method: 'red',
 event: 'blue',
 property: ''
}

var obj2 = {
 a_method : function() {},
 a_property: 1,
 onclick: undefined
}

function propertyKind(obj, p) {
 return  (_r_event.test(p) && (obj[p]==undefined || typeof(obj[p])=='function')) ? 'event'
   : (typeof(obj[p])=='function') ? 'method'
   : 'property';
}

var objectArr = ['window', 'obj2'];

for (var i=0; i<objectArr.length; i++) {
document.writeln('

for ', objectArr[i], '


');

 var obj = eval(objectArr[i]);
 for (var p in obj) {
   var kind = propertyKind(obj, p);
   document.writeln('obj.', p, ' is a ', kind.fontcolor(colorSetting[kind]), ': ', obj[p], '
');
 }

 document.writeln('

');
}

一個(gè)常常被開(kāi)發(fā)者忽略的事實(shí)是:JavaScript本身是沒(méi)有事件(Event)系統(tǒng)的。通常我們?cè)贘avaScript用到的onclick等事件,其實(shí)是IE的DOM模型提供的。從更內(nèi)核的角度上講:IE通過(guò)COM的接口屬性公布了一組事件接口給DOM。

有兩個(gè)原因,使得在JS中不能很好的識(shí)別“一個(gè)屬性是不是事件”:
 - COM接口中本身只有方法,屬性與事件,都是通過(guò)一組get/set方法來(lái)公布的。
 - JavaScript中,本身并沒(méi)有獨(dú)立的“事件”機(jī)制。

因此我們看到event的識(shí)別方法,是檢測(cè)屬性名是否是以'on'字符串開(kāi)頭(以'On'開(kāi)頭的是Qomo的約定)。接下來(lái),由于DOM對(duì)象中的事件是可以不指定處理函數(shù)的,這種情況下事件句柄為null值(Qomo采用相同的約定);在另外的一些情況下,用戶可能象obj2這樣,定義一個(gè)值為 undefined的事件。因此“事件”的判定條件被處理成一個(gè)復(fù)雜的表達(dá)式:   ("屬性以on/On開(kāi)頭" && ("值為null/undefined" || "類(lèi)型為function"))

另外,從上面的這段代碼的運(yùn)行結(jié)果來(lái)看。對(duì)DOM對(duì)象使用for..in,是不能列舉出對(duì)象方法來(lái)的。

最后說(shuō)明一點(diǎn)。事實(shí)上,在很多語(yǔ)言的實(shí)現(xiàn)中,“事件”都不是“面向?qū)ο蟆钡恼Z(yǔ)言特性,而是由具體的編程模型來(lái)提供的。例如Delphi中的事件驅(qū)動(dòng)機(jī)制,是由Win32操作系統(tǒng)中的窗口消息機(jī)制來(lái)提供,或者由用戶代碼在Component/Class中主動(dòng)調(diào)用事件處理函數(shù)來(lái)實(shí)現(xiàn)。

“事件”是一個(gè)“如何驅(qū)動(dòng)編程模型”的機(jī)制/問(wèn)題,而不是語(yǔ)言本身的問(wèn)題。然而以PME(property/method/event)為框架的OOP概念,已經(jīng)深入人心,所以當(dāng)編程語(yǔ)言或系統(tǒng)表現(xiàn)出這些特性來(lái)的時(shí)候,就已經(jīng)沒(méi)人關(guān)心“event究竟是誰(shuí)實(shí)現(xiàn)”的了。

3). this與with關(guān)鍵字的使用
------
在JavaScript的對(duì)象系統(tǒng)中,this關(guān)鍵字用在兩種地方:
  - 在構(gòu)造器函數(shù)中,指代新創(chuàng)建的對(duì)象實(shí)例
  - 在對(duì)象的方法被調(diào)用時(shí),指代調(diào)用該方法的對(duì)象實(shí)例

如果一個(gè)函數(shù)被作為普通函數(shù)(而不是對(duì)象方法)調(diào)用,那么在函數(shù)中的this關(guān)鍵字將指向window對(duì)象。與此相同的,如果this關(guān)鍵字不在任何函數(shù)中,那么他也指向window對(duì)象。

由于在JavaScript中不明確區(qū)分函數(shù)與方法。因此有些代碼看起來(lái)很奇怪:
//---------------------------------------------------------
// 函數(shù)的幾種可能調(diào)用形式
//---------------------------------------------------------
function foo() {
 // 下面的this指代調(diào)用該方法的對(duì)象實(shí)例
 if (this===window) {
   document.write('call a function.', '
');
 }
 else {
   document.write('call a method, by object: ', this.name, '
');
 }
}

function MyObject(name) {
 // 下面的this指代new關(guān)鍵字新創(chuàng)建實(shí)例
 this.name = name;
 this.foo = foo;
}

var obj1 = new MyObject('obj1');
var obj2 = new MyObject('obj2');

// 測(cè)試1: 作為函數(shù)調(diào)用
foo();

// 測(cè)試2: 作為對(duì)象方法的調(diào)用
obj1.foo();
obj2.foo();

// 測(cè)試3: 將函數(shù)作為“指定對(duì)象的”方法調(diào)用
foo.call(obj1);
foo.apply(obj2);

在上面的代碼里,obj1/obj2對(duì)foo()的調(diào)用是很普通的調(diào)用方法。??也就是在構(gòu)造器上,將一個(gè)函數(shù)指定為對(duì)象的方法。

而測(cè)試3中的call()與apply()就比較特殊。

在這個(gè)測(cè)試中,foo()仍然作為普通函數(shù)來(lái)調(diào)用,只是JavaScript的語(yǔ)言特性允許在call()/apply()時(shí),傳入一個(gè)對(duì)象實(shí)例來(lái)指定foo()的上下文環(huán)境中所出現(xiàn)的this關(guān)鍵字的引用。??需要注意的是,此時(shí)的foo()仍舊是一個(gè)普通函數(shù)調(diào)用,而不是對(duì)象方法調(diào)用。

與this“指示調(diào)用該方法的對(duì)象實(shí)例”有些類(lèi)同的,with()語(yǔ)法也用于限定“在一段代碼片段中默認(rèn)使用對(duì)象實(shí)例”。??如果不使用with()語(yǔ)法,那么這段代碼將受到更外層with()語(yǔ)句的影響;如果沒(méi)有更外層的with(),那么這段代碼的“默認(rèn)使用的對(duì)象實(shí)例”將是window。

然而需要注意的是this與with關(guān)鍵字不是互為影響的。如下面的代碼:
//---------------------------------------------------------
// 測(cè)試: this與with關(guān)鍵字不是互為影響的
//---------------------------------------------------------
function test() {
 with (obj2) {
   this.value = 8;
 }
}
var obj2 = new Object();
obj2.value = 10;

test();
document.writeln('obj2.value: ', obj2.value, '
');
document.writeln('window.value: ', window.value, '
');

你不能指望這樣的代碼在調(diào)用結(jié)束后,會(huì)使obj2.value屬性置值為8。這幾行代碼的結(jié)果是:window對(duì)象多了一個(gè)value屬性,并且值為8。

with(obj){...}這個(gè)語(yǔ)法,只能限定對(duì)obj的既有屬性的讀取,而不能主動(dòng)的聲明它。一旦with()里的對(duì)象沒(méi)有指定的屬性,或者with()限定了一個(gè)不是對(duì)象的數(shù)據(jù),那么結(jié)果會(huì)產(chǎn)生一個(gè)異常。

4). 使用in關(guān)鍵字的運(yùn)算
------
除了用for..in來(lái)反射對(duì)象的成員信息之外,JavaScript中也允許直接用in關(guān)鍵字去檢測(cè)對(duì)象是否有指定名字的屬性。

in關(guān)鍵字經(jīng)常被提及的原因并不是它檢測(cè)屬性是否存在的能力,因此在早期的代碼中,很多可喜歡用“if (!obj.propName) {}” 這樣的方式來(lái)檢測(cè)propName是否是有效的屬性。??很多時(shí)候,檢測(cè)有效性比檢測(cè)“是否存有該屬性”更有實(shí)用性。因此這種情況下,in只是一個(gè)可選的、官方的方案。

in關(guān)鍵字的重要應(yīng)用是高速字符串檢索。尤其是在只需要判定“字符串是否存在”的情況下。例如10萬(wàn)個(gè)字符串,如果存儲(chǔ)在數(shù)組中,那么檢索效率將會(huì)極差。
//---------------------------------------------------------
// 使用對(duì)象來(lái)檢索
//---------------------------------------------------------
function arrayToObject(arr) {
 for (var obj=new Object(), i=0, imax=arr.length; i<imax; i++) {
obj[arr[i]]=null;
 }
 return obj;
}

var
 arr = ['abc', 'def', 'ghi']; // more and more...
 obj = arrayToObject(arr);

function valueInArray(v) {
 for (var i=0, imax=arr.length; i<imax; i++) {
if (arr[i]==v) return true;
 }

 return false;
}

function valueInObject(v) {
 return v in obj;
}

這種使用關(guān)鍵字in的方法,也存在一些限制。例如只能查找字符串,而數(shù)組元素可以是任意值。另外,arrayToObject()也存在一些開(kāi)銷(xiāo),這使得它不適合于頻繁變動(dòng)的查找集。最后,(我想你可能已經(jīng)注意到了)使用對(duì)象來(lái)查找的時(shí)候并不能準(zhǔn)確定位到查找數(shù)據(jù),而數(shù)組中可以指向結(jié)果的下標(biāo)。

5). 使用instanceof關(guān)鍵字的運(yùn)算
------
在JavaScript中提供了instanceof關(guān)鍵字來(lái)檢測(cè)實(shí)例的類(lèi)型。這在前面討論它的“五重身份”時(shí)已經(jīng)講過(guò)。但instanceof的問(wèn)題是,它總是列舉整個(gè)原型鏈以檢測(cè)類(lèi)型(關(guān)于原型繼承的原理在“構(gòu)造與析構(gòu)”小節(jié)講述),如:
//---------------------------------------------------------
// instanceof使用中的問(wèn)題
//---------------------------------------------------------
function MyObject() {
 // ...
}

function MyObject2() {
 // ...
}
MyObject2.prototype = new MyObject();

obj1 = new MyObject();
obj2 = new MyObject2();

document.writeln(obj1 instanceof MyObject, '
');
document.writeln(obj2 instanceof MyObject, '
');

我們看到,obj1與obj2都是MyObject的實(shí)例,但他們是不同的構(gòu)造函數(shù)產(chǎn)生的。??注意,這在面向?qū)ο罄碚撝姓_的:因?yàn)閛bj2是MyObject的子類(lèi)實(shí)例,因此它具有與obj1相同的特性。在應(yīng)用中這是obj2的多態(tài)性的體現(xiàn)之一。

但是,即便如此,我們也必須面臨這樣的問(wèn)題:如何知道obj2與obj1是否是相同類(lèi)型的實(shí)例呢???也就是說(shuō),連構(gòu)造器都相同?

instanceof關(guān)鍵字不提供這樣的機(jī)制。一個(gè)提供實(shí)現(xiàn)這種檢測(cè)的能力的,是Object.constructor屬性。??但請(qǐng)先記住,它的使用遠(yuǎn)比你想象的要難。

好的,問(wèn)題先到這里。constructor屬性已經(jīng)涉及到“構(gòu)造與析構(gòu)”的問(wèn)題,這個(gè)我們后面再講?!霸屠^承”、“構(gòu)造與析構(gòu)”是JavaScript的OOP中的主要問(wèn)題、核心問(wèn)題,以及“致命問(wèn)題”。

6). null與undefined
------
在JavaScript中,null與undefined曾一度使我迷惑。下面的文字,有利于
你更清晰的認(rèn)知它(或者讓你更迷惑):
  - null是關(guān)鍵字;undefined是Global對(duì)象的一個(gè)屬性。
  - null是對(duì)象(空對(duì)象, 沒(méi)有任何屬性和方法);undefined是undefined類(lèi)
    型的值。試試下面的代碼:
      document.writeln(typeof null);
      document.writeln(typeof undefined);
  - 對(duì)象模型中,所有的對(duì)象都是Object或其子類(lèi)的實(shí)例,但null對(duì)象例外:
      document.writeln(null instanceof Object);
  - null“等值(==)”于undefined,但不“全等值(===)”于undefined:
      document.writeln(null == undefined);
      document.writeln(null == undefined);
  - 運(yùn)算時(shí)null與undefined都可以被類(lèi)型轉(zhuǎn)換為false,但不等值于false:
      document.writeln(!null, !undefined);
      document.writeln(null==false);
      document.writeln(undefined==false);
[@more@]

“JavaScript面向?qū)ο蟮闹С衷趺磳?shí)現(xiàn)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

文章標(biāo)題:JavaScript面向?qū)ο蟮闹С衷趺磳?shí)現(xiàn)-創(chuàng)新互聯(lián)
轉(zhuǎn)載注明:http://muchs.cn/article4/djehoe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化企業(yè)建站、網(wǎng)站維護(hù)做網(wǎng)站、軟件開(kāi)發(fā)、電子商務(wù)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)