中文字幕日韩一区二区_国产一区二区av_国产毛片av_久久久久国产一区_色婷婷电影_国产一区二区精品

javascript prototype 原型鏈

JavaScript中的prototype概念恰如其分地反映了這個(gè)詞的內(nèi)含,我們不能將其理解為C++的prototype那種預(yù)先聲明的概念。
JavaScript 的所有function類型的對(duì)象都有一個(gè)prototype屬性。這個(gè)prototype屬性本身又是一個(gè)object類型的對(duì)象,因此我們也可以給這個(gè)prototype對(duì)象添加任意的屬性和方法。既然prototype是對(duì)象的“原型”,那么由該函數(shù)構(gòu)造出來的對(duì)象應(yīng)該都會(huì)具有這個(gè)“原型”的特性。事實(shí)上,在構(gòu)造函數(shù)的prototype上定義的所有屬性和方法,都是可以通過其構(gòu)造的對(duì)象直接訪問和調(diào)用的。也可以這么說,prototype提供了一群同類對(duì)象共享屬性和方法的機(jī)制。
我們先來看看下面的代碼:
function Person(name)
{
this.name = name; //設(shè)置對(duì)象屬性,每個(gè)對(duì)象各自一份屬性數(shù)據(jù)
};
Person.prototype.SayHello = function() //給Person函數(shù)的prototype添加SayHello方法。
{
alert("Hello, I'm " + this.name);
}
var BillGates = new Person("Bill Gates"); //創(chuàng)建BillGates對(duì)象
var SteveJobs = new Person("Steve Jobs"); //創(chuàng)建SteveJobs對(duì)象
BillGates.SayHello(); //通過BillGates對(duì)象直接調(diào)用到SayHello方法
SteveJobs.SayHello(); //通過SteveJobs對(duì)象直接調(diào)用到SayHello方法
alert(BillGates.SayHello == SteveJobs.SayHello); //因?yàn)閮蓚€(gè)對(duì)象是共享prototype的SayHello,所以顯示:true
程序運(yùn)行的結(jié)果表明,構(gòu)造函數(shù)的prototype上定義的方法確實(shí)可以通過對(duì)象直接調(diào)用到,而且代碼是共享的。顯然,把方法設(shè)置到prototype的寫法顯得優(yōu)雅多了,盡管調(diào)用形式?jīng)]有變,但邏輯上卻體現(xiàn)了方法與類的關(guān)系,相對(duì)前面的寫法,更容易理解和組織代碼。
那么,對(duì)于多層次類型的構(gòu)造函數(shù)情況又如何呢?
我們?cè)賮砜聪旅娴拇a:
1 function Person(name) //基類構(gòu)造函數(shù)
2 {
3 this.name = name;
4 };
5
6 Person.prototype.SayHello = function() //給基類構(gòu)造函數(shù)的prototype添加方法
7 {
8 alert("Hello, I'm " + this.name);
9 };
10
11 function Employee(name, salary) //子類構(gòu)造函數(shù)
12 {
13 Person.call(this, name); //調(diào)用基類構(gòu)造函數(shù)
14 this.salary = salary;
15 };
16
17 Employee.prototype = new Person(); //建一個(gè)基類的對(duì)象作為子類原型的原型,這里很有意思
18
19 Employee.prototype.ShowMeTheMoney = function() //給子類添構(gòu)造函數(shù)的prototype添加方法
20 {
21 alert(this.name + " $" + this.salary);
22 };
23
24 var BillGates = new Person("Bill Gates"); //創(chuàng)建基類Person的BillGates對(duì)象
25 var SteveJobs = new Employee("Steve Jobs", 1234); //創(chuàng)建子類Employee的SteveJobs對(duì)象
26
27 BillGates.SayHello(); //通過對(duì)象直接調(diào)用到prototype的方法
28 SteveJobs.SayHello(); //通過子類對(duì)象直接調(diào)用基類prototype的方法,關(guān)注!
29 SteveJobs.ShowMeTheMoney(); //通過子類對(duì)象直接調(diào)用子類prototype的方法
30
31 alert(BillGates.SayHello == SteveJobs.SayHello); //顯示:true,表明prototype的方法是共享的
這段代碼的第17行,構(gòu)造了一個(gè)基類的對(duì)象,并將其設(shè)為子類構(gòu)造函數(shù)的prototype,這是很有意思的。這樣做的目的就是為了第28行,通過子類對(duì)象也可以直接調(diào)用基類prototype的方法。為什么可以這樣呢?
原來,在JavaScript中,prototype不但能讓對(duì)象共享自己財(cái)富,而且prototype還有尋根問祖的天性,從而使得先輩們的遺產(chǎn)可以代代相傳。當(dāng)從一個(gè)對(duì)象那里讀取屬性或調(diào)用方法時(shí),如果該對(duì)象自身不存在這樣的屬性或方法,就會(huì)去自己關(guān)聯(lián)的prototype對(duì)象那里尋找;如果 prototype沒有,又會(huì)去prototype自己關(guān)聯(lián)的前輩prototype那里尋找,直到找到或追溯過程結(jié)束為止。
JavaScript內(nèi)部,對(duì)象的屬性和方法追溯機(jī)制是通過所謂的prototype鏈來實(shí)現(xiàn)的。當(dāng)用new操作符構(gòu)造對(duì)象時(shí),也會(huì)同時(shí)將構(gòu)造函數(shù)的 prototype對(duì)象指派給新創(chuàng)建的對(duì)象,成為該對(duì)象內(nèi)置的原型對(duì)象。對(duì)象內(nèi)置的原型對(duì)象應(yīng)該是對(duì)外不可見的,盡管有些瀏覽器(如Firefox)可以讓我們?cè)L問這個(gè)內(nèi)置原型對(duì)象,但并不建議這樣做。內(nèi)置的原型對(duì)象本身也是對(duì)象,也有自己關(guān)聯(lián)的原型對(duì)象,這樣就形成了所謂的原型鏈。
在原型鏈的最末端,就是Object構(gòu)造函數(shù)prototype屬性指向的那一個(gè)原型對(duì)象。這個(gè)原型對(duì)象是所有對(duì)象的最老祖先,這個(gè)老祖宗實(shí)現(xiàn)了諸如 toString等所有對(duì)象天生就該具有的方法。其他內(nèi)置構(gòu)造函數(shù),如Function, Boolean, String, Date和RegExp等的prototype都是從這個(gè)老祖宗傳承下來的,但他們各自又定義了自身的屬性和方法,從而他們的子孫就表現(xiàn)出各自宗族的那些特征。
這不就是“繼承”嗎?是的,這就是“繼承”,是JavaScript特有的“原型繼承”。
“ 原型繼承”是慈祥而又嚴(yán)厲的。原形對(duì)象將自己的屬性和方法無私地貢獻(xiàn)給孩子們使用,也并不強(qiáng)迫孩子們必須遵從,允許一些頑皮孩子按自己的興趣和愛好獨(dú)立行事。從這點(diǎn)上看,原型對(duì)象是一位慈祥的母親。然而,任何一個(gè)孩子雖然可以我行我素,但卻不能動(dòng)原型對(duì)象既有的財(cái)產(chǎn),因?yàn)槟强赡軙?huì)影響到其他孩子的利益。從這一點(diǎn)上看,原型對(duì)象又象一位嚴(yán)厲的父親。我們來看看下面的代碼就可以理解這個(gè)意思了:
function Person(name)
{
this.name = name;
};
Person.prototype.company = "Microsoft"; //原型的屬性
Person.prototype.SayHello = function() //原型的方法
{
alert("Hello, I'm " + this.name + " of " + this.company);
};
var BillGates = new Person("Bill Gates");
BillGates.SayHello(); //由于繼承了原型的東西,規(guī)規(guī)矩矩輸出:Hello, I'm Bill Gates
var SteveJobs = new Person("Steve Jobs");
SteveJobs.company = "Apple"; //設(shè)置自己的company屬性,掩蓋了原型的company屬性
SteveJobs.SayHello = function() //實(shí)現(xiàn)了自己的SayHello方法,掩蓋了原型的SayHello方法
{
alert("Hi, " + this.name + " like " + this.company + ", ha ha ha ");
};
SteveJobs.SayHello(); //都是自己覆蓋的屬性和方法,輸出:Hi, Steve Jobs like Apple, ha ha ha
BillGates.SayHello(); //SteveJobs的覆蓋沒有影響原型對(duì)象,BillGates還是按老樣子輸出
對(duì)象可以掩蓋原型對(duì)象的那些屬性和方法,一個(gè)構(gòu)造函數(shù)原型對(duì)象也可以掩蓋上層構(gòu)造函數(shù)原型對(duì)象既有的屬性和方法。這種掩蓋其實(shí)只是在對(duì)象自己身上創(chuàng)建了新的屬性和方法,只不過這些屬性和方法與原型對(duì)象的那些同名而已。JavaScript就是用這簡(jiǎn)單的掩蓋機(jī)制實(shí)現(xiàn)了對(duì)象的“多態(tài)”性,與靜態(tài)對(duì)象語(yǔ)言的虛函數(shù)和重載(override)概念不謀而合。
然而,比靜態(tài)對(duì)象語(yǔ)言更神奇的是,我們可以隨時(shí)給原型對(duì)象動(dòng)態(tài)添加新的屬性和方法,從而動(dòng)態(tài)地?cái)U(kuò)展基類的功能特性。這在靜態(tài)對(duì)象語(yǔ)言中是很難想象的。我們來看下面的代碼:
function Person(name)
{
this.name = name;
};
Person.prototype.SayHello = function() //建立對(duì)象前定義的方法
{
alert("Hello, I'm " + this.name);
};
var BillGates = new Person("Bill Gates"); //建立對(duì)象
BillGates.SayHello();
Person.prototype.Retire = function() //建立對(duì)象后再動(dòng)態(tài)擴(kuò)展原型的方法
{
alert("Poor " + this.name + ", bye bye!");
};
BillGates.Retire(); //動(dòng)態(tài)擴(kuò)展的方法即可被先前建立的對(duì)象立即調(diào)用
阿彌佗佛,原型繼承竟然可以玩出有這樣的法術(shù)!
原型擴(kuò)展
想必君的悟性極高,可能你會(huì)這樣想:如果在JavaScript內(nèi)置的那些如Object和Function等函數(shù)的prototype上添加些新的方法和屬性,是不是就能擴(kuò)展JavaScript的功能呢?
那么,恭喜你,你得到了!
在 AJAX技術(shù)迅猛發(fā)展的今天,許多成功的AJAX項(xiàng)目的JavaScript運(yùn)行庫(kù)都大量擴(kuò)展了內(nèi)置函數(shù)的prototype功能。比如微軟的 ASP.NET AJAX,就給這些內(nèi)置函數(shù)及其prototype添加了大量的新特性,從而增強(qiáng)了JavaScript的功能。
我們來看一段摘自MicrosoftAjax.debug.js中的代碼:
String.prototype.trim = function String$trim() {
if (arguments.length !== 0) throw Error.parameterCount();
return this.replace(/^/s+|/s+$/g, '');
}
這段代碼就是給內(nèi)置String函數(shù)的prototype擴(kuò)展了一個(gè)trim方法,于是所有的String類對(duì)象都有了trim方法了。有了這個(gè)擴(kuò)展,今后要去除字符串兩段的空白,就不用再分別處理了,因?yàn)槿魏巫址加辛诉@個(gè)擴(kuò)展功能,只要調(diào)用即可,真的很方便。
當(dāng)然,幾乎很少有人去給Object的prototype添加方法,因?yàn)槟菚?huì)影響到所有的對(duì)象,除非在你的架構(gòu)中這種方法的確是所有對(duì)象都需要的。
前兩年,微軟在設(shè)計(jì)AJAX類庫(kù)的初期,用了一種被稱為“閉包”(closure)的技術(shù)來模擬“類”。其大致模型如下:
function Person(firstName, lastName, age)
{
//私有變量:
var _firstName = firstName;
var _lastName = lastName;
//公共變量:
this.age = age;
//方法:
this.getName = function()
{
return(firstName + " " + lastName);
};
this.SayHello = function()
{
alert("Hello, I'm " + firstName + " " + lastName);
};
};
var BillGates = new Person("Bill", "Gates", 53);
var SteveJobs = new Person("Steve", "Jobs", 53);
BillGates.SayHello();
SteveJobs.SayHello();
alert(BillGates.getName() + " " + BillGates.age);
alert(BillGates.firstName); //這里不能訪問到私有變量
很顯然,這種模型的類描述特別象C#語(yǔ)言的描述形式,在一個(gè)構(gòu)造函數(shù)里依次定義了私有成員、公共屬性和可用的方法,顯得非常優(yōu)雅嘛。特別是“閉包”機(jī)制可以模擬對(duì)私有成員的保護(hù)機(jī)制,做得非常漂亮。
所謂的“閉包”,就是在構(gòu)造函數(shù)體內(nèi)定義另外的函數(shù)作為目標(biāo)對(duì)象的方法函數(shù),而這個(gè)對(duì)象的方法函數(shù)反過來引用外層外層函數(shù)體中的臨時(shí)變量。這使得只要目標(biāo)對(duì)象在生存期內(nèi)始終能保持其方法,就能間接保持原構(gòu)造函數(shù)體當(dāng)時(shí)用到的臨時(shí)變量值。盡管最開始的構(gòu)造函數(shù)調(diào)用已經(jīng)結(jié)束,臨時(shí)變量的名稱也都消失了,但在目標(biāo)對(duì)象的方法內(nèi)卻始終能引用到該變量的值,而且該值只能通這種方法來訪問。即使再次調(diào)用相同的構(gòu)造函數(shù),但只會(huì)生成新對(duì)象和方法,新的臨時(shí)變量只是對(duì)應(yīng)新的值,和上次那次調(diào)用的是各自獨(dú)立的。的確很巧妙!
但是前面我們說過,給每一個(gè)對(duì)象設(shè)置一份方法是一種很大的浪費(fèi)。還有,“閉包”這種間接保持變量值的機(jī)制,往往會(huì)給JavaSript的垃圾回收器制造難題。特別是遇到對(duì)象間復(fù)雜的循環(huán)引用時(shí),垃圾回收的判斷邏輯非常復(fù)雜。無獨(dú)有偶,IE瀏覽器早期版本確實(shí)存在JavaSript垃圾回收方面的內(nèi)存泄漏問題。再加上“閉包”模型在性能測(cè)試方面的表現(xiàn)不佳,微軟最終放棄了“閉包” 模型,而改用“原型”模型。正所謂“有得必有失”嘛。
原型模型需要一個(gè)構(gòu)造函數(shù)來定義對(duì)象的成員,而方法卻依附在該構(gòu)造函數(shù)的原型上。大致寫法如下:
//定義構(gòu)造函數(shù)
function Person(name)
{
this.name = name; //在構(gòu)造函數(shù)中定義成員
};
//方法定義到構(gòu)造函數(shù)的prototype上
Person.prototype.SayHello = function()
{
alert("Hello, I'm " + this.name);
};
//子類構(gòu)造函數(shù)
function Employee(name, salary)
{
Person.call(this, name); //調(diào)用上層構(gòu)造函數(shù)
this.salary = salary; //擴(kuò)展的成員
};
//子類構(gòu)造函數(shù)首先需要用上層構(gòu)造函數(shù)來建立prototype對(duì)象,實(shí)現(xiàn)繼承的概念
Employee.prototype = new Person() //只需要其prototype的方法,此對(duì)象的成員沒有任何意義!
//子類方法也定義到構(gòu)造函數(shù)之上
Employee.prototype.ShowMeTheMoney = function()
{
alert(this.name + " $" + this.salary);
};
var BillGates = new Person("Bill Gates");
BillGates.SayHello();
var SteveJobs = new Employee("Steve Jobs", 1234);
SteveJobs.SayHello();
SteveJobs.ShowMeTheMoney();
原型類模型雖然不能模擬真正的私有變量,而且也要分兩部分來定義類,顯得不怎么“優(yōu)雅”。不過,對(duì)象間的方法是共享的,不會(huì)遇到垃圾回收問題,而且性能優(yōu)于“閉包”模型。正所謂“有失必有得”嘛。
在原型模型中,為了實(shí)現(xiàn)類繼承,必須首先將子類構(gòu)造函數(shù)的prototype設(shè)置為一個(gè)父類的對(duì)象實(shí)例。創(chuàng)建這個(gè)父類對(duì)象實(shí)例的目的就是為了構(gòu)成原型鏈,以起到共享上層原型方法作用。但創(chuàng)建這個(gè)實(shí)例對(duì)象時(shí),上層構(gòu)造函數(shù)也會(huì)給它設(shè)置對(duì)象成員,這些對(duì)象成員對(duì)于繼承來說是沒有意義的。雖然,我們也沒有給構(gòu)造函數(shù)傳遞參數(shù),但確實(shí)創(chuàng)建了若干沒有用的成員,盡管其值是undefined,這也是一種浪費(fèi)啊。
唉!世界上沒有完美的事情?。?
原型真諦
正當(dāng)我們感概萬(wàn)分時(shí),天空中一道紅光閃過,祥云中出現(xiàn)了觀音菩薩。只見她手持玉凈瓶,輕拂翠柳枝,灑下幾滴甘露,頓時(shí)讓JavaScript又添新的靈氣。
觀音灑下的甘露在JavaScript的世界里凝結(jié)成塊,成為了一種稱為“語(yǔ)法甘露”的東西。這種語(yǔ)法甘露可以讓我們編寫的代碼看起來更象對(duì)象語(yǔ)言。
要想知道這“語(yǔ)法甘露”為何物,就請(qǐng)君側(cè)耳細(xì)聽。
在理解這些語(yǔ)法甘露之前,我們需要重新再回顧一下JavaScript構(gòu)造對(duì)象的過程。
我們已經(jīng)知道,用 var anObject = new aFunction() 形式創(chuàng)建對(duì)象的過程實(shí)際上可以分為三步:第一步是建立一個(gè)新對(duì)象;第二步將該對(duì)象內(nèi)置的原型對(duì)象設(shè)置為構(gòu)造函數(shù)prototype引用的那個(gè)原型對(duì)象;第三步就是將該對(duì)象作為this參數(shù)調(diào)用構(gòu)造函數(shù),完成成員設(shè)置等初始化工作。對(duì)象建立之后,對(duì)象上的任何訪問和操作都只與對(duì)象自身及其原型鏈上的那串對(duì)象有關(guān),與構(gòu)造函數(shù)再扯不上關(guān)系了。換句話說,構(gòu)造函數(shù)只是在創(chuàng)建對(duì)象時(shí)起到介紹原型對(duì)象和初始化對(duì)象兩個(gè)作用。
那么,我們能否自己定義一個(gè)對(duì)象來當(dāng)作原型,并在這個(gè)原型上描述類,然后將這個(gè)原型設(shè)置給新創(chuàng)建的對(duì)象,將其當(dāng)作對(duì)象的類呢?我們又能否將這個(gè)原型中的一個(gè)方法當(dāng)作構(gòu)造函數(shù),去初始化新建的對(duì)象呢?例如,我們定義這樣一個(gè)原型對(duì)象:
var Person = //定義一個(gè)對(duì)象來作為原型類
{
Create: function(name, age) //這個(gè)當(dāng)構(gòu)造函數(shù)
{
this.name = name;
this.age = age;
},
SayHello: function() //定義方法
{
alert("Hello, I'm " + this.name);
},
HowOld: function() //定義方法
{
alert(this.name + " is " + this.age + " years old.");
}
};
這個(gè)JSON形式的寫法多么象一個(gè)C#的類啊!既有構(gòu)造函數(shù),又有各種方法。如果可以用某種形式來創(chuàng)建對(duì)象,并將對(duì)象的內(nèi)置的原型設(shè)置為上面這個(gè)“類”對(duì)象,不就相當(dāng)于創(chuàng)建該類的對(duì)象了嗎?
但遺憾的是,我們幾乎不能訪問到對(duì)象內(nèi)置的原型屬性!盡管有些瀏覽器可以訪問到對(duì)象的內(nèi)置原型,但這樣做的話就只能限定了用戶必須使用那種瀏覽器。這也幾乎不可行。
那么,我們可不可以通過一個(gè)函數(shù)對(duì)象來做媒介,利用該函數(shù)對(duì)象的prototype屬性來中轉(zhuǎn)這個(gè)原型,并用new操作符傳遞給新建的對(duì)象呢?
其實(shí),象這樣的代碼就可以實(shí)現(xiàn)這一目標(biāo):
function anyfunc(){}; //定義一個(gè)函數(shù)軀殼
anyfunc.prototype = Person; //將原型對(duì)象放到中轉(zhuǎn)站prototype
var BillGates = new anyfunc(); //新建對(duì)象的內(nèi)置原型將是我們期望的原型對(duì)象
不過,這個(gè)anyfunc函數(shù)只是一個(gè)軀殼,在使用過這個(gè)軀殼之后它就成了多余的東西了,而且這和直接使用構(gòu)造函數(shù)來創(chuàng)建對(duì)象也沒啥不同,有點(diǎn)不爽。
可是,如果我們將這些代碼寫成一個(gè)通用函數(shù),而那個(gè)函數(shù)軀殼也就成了函數(shù)內(nèi)的函數(shù),這個(gè)內(nèi)部函數(shù)不就可以在外層函數(shù)退出作用域后自動(dòng)消亡嗎?而且,我們可以將原型對(duì)象作為通用函數(shù)的參數(shù),讓通用函數(shù)返回創(chuàng)建的對(duì)象。我們需要的就是下面這個(gè)形式:
function New(aClass, aParams) //通用創(chuàng)建函數(shù)
{
function new_() //定義臨時(shí)的中轉(zhuǎn)函數(shù)殼
{
aClass.Create.apply(this, aParams); //調(diào)用原型中定義的的構(gòu)造函數(shù),中轉(zhuǎn)構(gòu)造邏輯及構(gòu)造參數(shù)
};
new_.prototype = aClass; //準(zhǔn)備中轉(zhuǎn)原型對(duì)象
return new new_(); //返回建立最終建立的對(duì)象
};
var Person = //定義的類
{
Create: function(name, age)
{
this.name = name;
this.age = age;
},
SayHello: function()
{
alert("Hello, I'm " + this.name);
},
HowOld: function()
{
alert(this.name + " is " + this.age + " years old.");
}
};
var BillGates = New(Person, ["Bill Gates", 53]); //調(diào)用通用函數(shù)創(chuàng)建對(duì)象,并以數(shù)組形式傳遞構(gòu)造參數(shù)
BillGates.SayHello();
BillGates.HowOld();
alert(BillGates.constructor == Object); //輸出:true
這里的通用函數(shù)New()就是一個(gè)“語(yǔ)法甘露”!這個(gè)語(yǔ)法甘露不但中轉(zhuǎn)了原型對(duì)象,還中轉(zhuǎn)了構(gòu)造函數(shù)邏輯及構(gòu)造參數(shù)。
有趣的是,每次創(chuàng)建完對(duì)象退出New函數(shù)作用域時(shí),臨時(shí)的new_函數(shù)對(duì)象會(huì)被自動(dòng)釋放。由于new_的prototype屬性被設(shè)置為新的原型對(duì)象,其原來的原型對(duì)象和new_之間就已解開了引用鏈,臨時(shí)函數(shù)及其原來的原型對(duì)象都會(huì)被正確回收了。上面代碼的最后一句證明,新創(chuàng)建的對(duì)象的 constructor屬性返回的是Object函數(shù)。其實(shí)新建的對(duì)象自己及其原型里沒有constructor屬性,那返回的只是最頂層原型對(duì)象的構(gòu)造函數(shù),即Object。
有了New這個(gè)語(yǔ)法甘露,類的定義就很像C#那些靜態(tài)對(duì)象語(yǔ)言的形式了,這樣的代碼顯得多么文靜而優(yōu)雅??!
當(dāng)然,這個(gè)代碼僅僅展示了“語(yǔ)法甘露”的概念。我們還需要多一些的語(yǔ)法甘露,才能實(shí)現(xiàn)用簡(jiǎn)潔而優(yōu)雅的代碼書寫類層次及其繼承關(guān)系。好了,我們?cè)賮砜匆粋€(gè)更豐富的示例吧:
//語(yǔ)法甘露:
var object = //定義小寫的object基本類,用于實(shí)現(xiàn)最基礎(chǔ)的方法等
{
isA: function(aType) //一個(gè)判斷類與類之間以及對(duì)象與類之間關(guān)系的基礎(chǔ)方法
{
var self = this;
while(self)
{
if (self == aType)
return true;
self = self.Type;
};
return false;
}
};
function Class(aBaseClass, aClassDefine) //創(chuàng)建類的函數(shù),用于聲明類及繼承關(guān)系
{
function class_() //創(chuàng)建類的臨時(shí)函數(shù)殼
{
this.Type = aBaseClass; //我們給每一個(gè)類約定一個(gè)Type屬性,引用其繼承的類
for(var member in aClassDefine)
this[member] = aClassDefine[member]; //復(fù)制類的全部定義到當(dāng)前創(chuàng)建的類
};
class_.prototype = aBaseClass;
return new class_();
};
function New(aClass, aParams) //創(chuàng)建對(duì)象的函數(shù),用于任意類的對(duì)象創(chuàng)建
{
function new_() //創(chuàng)建對(duì)象的臨時(shí)函數(shù)殼
{
this.Type = aClass; //我們也給每一個(gè)對(duì)象約定一個(gè)Type屬性,據(jù)此可以訪問到對(duì)象所屬的類
if (aClass.Create)
aClass.Create.apply(this, aParams); //我們約定所有類的構(gòu)造函數(shù)都叫Create,這和DELPHI比較相似
};
new_.prototype = aClass;
return new new_();
};
//語(yǔ)法甘露的應(yīng)用效果:
var Person = Class(object, //派生至object基本類
{
Create: function(name, age)
{
this.name = name;
this.age = age;
},
SayHello: function()
{
alert("Hello, I'm " + this.name + ", " + this.age + " years old.");
}
});
var Employee = Class(Person, //派生至Person類,是不是和一般對(duì)象語(yǔ)言很相似?
{
Create: function(name, age, salary)
{
Person.Create.call(this, name, age); //調(diào)用基類的構(gòu)造函數(shù)
this.salary = salary;
},
ShowMeTheMoney: function()
{
alert(this.name + " $" + this.salary);
}
});
var BillGates = New(Person, ["Bill Gates", 53]);
var SteveJobs = New(Employee, ["Steve Jobs", 53, 1234]);
BillGates.SayHello();
SteveJobs.SayHello();
SteveJobs.ShowMeTheMoney();
var LittleBill = New(BillGates.Type, ["Little Bill", 6]); //根據(jù)BillGate的類型創(chuàng)建LittleBill
LittleBill.SayHello();
alert(BillGates.isA(Person)); //true
alert(BillGates.isA(Employee)); //false
alert(SteveJobs.isA(Person)); //true
alert(Person.isA(Employee)); //false
alert(Employee.isA(Person)); //true
“語(yǔ)法甘露”不用太多,只要那么一點(diǎn)點(diǎn),就能改觀整個(gè)代碼的易讀性和流暢性,從而讓代碼顯得更優(yōu)雅。有了這些語(yǔ)法甘露,JavaScript就很像一般對(duì)象語(yǔ)言了,寫起代碼了感覺也就爽多了!
令人高興的是,受這些甘露滋養(yǎng)的JavaScript程序效率會(huì)更高。因?yàn)槠湓蛯?duì)象里既沒有了毫無用處的那些對(duì)象級(jí)的成員,而且還不存在 constructor屬性體,少了與構(gòu)造函數(shù)間的牽連,但依舊保持了方法的共享性。這讓JavaScript在追溯原型鏈和搜索屬性及方法時(shí),少費(fèi)許多工夫啊。
我們就把這種形式稱為“甘露模型”吧!其實(shí),這種“甘露模型”的原型用法才是符合prototype概念的本意,才是的JavaScript原型的真諦!
想必微軟那些設(shè)計(jì)AJAX架構(gòu)的工程師看到這個(gè)甘露模型時(shí),肯定后悔沒有早點(diǎn)把AJAX部門從美國(guó)搬到咱中國(guó)的觀音廟來,錯(cuò)過了觀音菩薩的點(diǎn)化。當(dāng)然,我們也只能是在代碼的示例中,把Bill Gates當(dāng)作對(duì)象玩玩,真要讓他放棄上帝轉(zhuǎn)而皈依我佛肯定是不容易的,機(jī)緣未到??!如果哪天你在微軟新出的AJAX類庫(kù)中看到這種甘露模型,那才是真正的緣分!
編程的快樂
在軟件工業(yè)迅猛發(fā)展的今天,各式各樣的編程語(yǔ)言層出不窮,新語(yǔ)言的誕生,舊語(yǔ)言的演化,似乎已經(jīng)讓我們眼花繚亂。為了適應(yīng)面向?qū)ο缶幊痰某绷鳎?a href=/itjie/Javajishu/ target=_blank class=infotextkey>JavaScript語(yǔ)言也在向完全面向?qū)ο蟮姆较虬l(fā)展,新的JavaScript標(biāo)準(zhǔn)已經(jīng)從語(yǔ)義上擴(kuò)展了許多面向?qū)ο蟮男略亍Ec此相反的是,許多靜態(tài)的對(duì)象語(yǔ)言也在向JavaScript的那種簡(jiǎn)潔而幽雅的方向發(fā)展。例如,新版本的C#語(yǔ)言就吸收了JSON那樣的簡(jiǎn)潔表示法,以及一些其他形式的JavaScript特性。
我們應(yīng)該看到,隨著RIA(強(qiáng)互聯(lián)應(yīng)用)的發(fā)展和普及,AJAX技術(shù)也將逐漸淡出江湖,JavaScript也將最終消失或演化成其他形式的語(yǔ)言。但不管編程語(yǔ)言如何發(fā)展和演化,編程世界永遠(yuǎn)都會(huì)在“數(shù)據(jù)”與“代碼”這千絲萬(wàn)縷的糾纏中保持著無限的生機(jī)。只要我們能看透這一點(diǎn),我們就能很容易地學(xué)習(xí)和理解軟件世界的各種新事物。不管是已熟悉的過程式編程,還是正在發(fā)展的函數(shù)式編程,以及未來量子糾纏態(tài)的大規(guī)模并行式編程,我們都有足夠的法力來化解一切復(fù)雜的難題。

JavaScript技術(shù)javascript prototype 原型鏈,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 亚洲网在线 | 成人免费毛片在线观看 | www.色综合 | 99久久精品免费看国产四区 | 久久亚洲国产 | 蜜桃视频在线观看免费视频网站www | 精品九九| 草b视频| 久久精品这里精品 | 一区二区三区四区免费在线观看 | 中文字幕在线观看 | 亚洲精品免费视频 | 精品一区二区三区不卡 | 久久这里只有 | 国产在线h | 国产丝袜一区二区三区免费视频 | 国产成人精品久久 | 国产丝袜一区二区三区免费视频 | 欧美不卡| 亚洲午夜网| 精品亚洲一区二区三区 | 在线看亚洲 | 香蕉婷婷 | 国产精品1区2区3区 国产在线观看一区 | 成人免费一区二区三区视频网站 | 在线区| 亚洲精品91 | 欧美日韩视频在线 | 精品一级 | 99精品国自产在线观看 | 欧美成人黄色小说 | 精品不卡| 久久91精品国产 | 久久久精彩视频 | 黄网站在线播放 | 成人性生交大片免费看中文带字幕 | 欧美视频免费在线 | 日韩资源| 九九亚洲 | 亚洲精品成人免费 | 久久在线 |