javascript學(xué)習(xí)筆記(九)javascript中的原型(prototype)及原型鏈的繼承方式
我們首先來看以下代碼:
function person(name, age) {
this.name = name;
this.age = age;
}
person.prototype.getInfo = function() {
alert("My name is "+this.name+", and I have "+this.age+" years old");
}
var zhangchen = new person("zhangchen", 23);
zhangchen.getInfo(); //output My name is zhangchen, and I have 23 years old;
從運(yùn)行的結(jié)果我們可以看出,通過關(guān)鍵字new創(chuàng)建的zhangchen這個(gè)對(duì)象繼承了person中通過原型定義的getInfo()方法。下面我們具體來看新建的zhangchen這個(gè)對(duì)象是如何繼承person對(duì)象的屬性和方法的。
原型:在使用 JavaScript 的面向?qū)ο缶幊讨?,原型?duì)象是個(gè)核心概念。在 JavaScript 中對(duì)象是作為現(xiàn)有示例(即原型)對(duì)象的副本而創(chuàng)建的,該名稱就來自于這一概念。此原型對(duì)象的任何屬性和方法都將顯示為從原型的構(gòu)造函數(shù)創(chuàng)建的對(duì)象的屬性和方法??梢哉f,這些對(duì)象從其原型繼承了屬性和方法。當(dāng)創(chuàng)建zhangchen對(duì)象時(shí):
var zhangchen = new company("zhangchen", 23);
zhangchen 所引用的對(duì)象將從它的原型繼承屬性和方法,對(duì)象 zhangchen 的原型來自構(gòu)造函數(shù)(在這里是函數(shù) person)的屬性。
在 JavaScript 中,每個(gè)函數(shù)都有名為prototype的屬性,用于引用原型對(duì)象。此原型對(duì)象又有名為constructor的屬性,它反過來引用函數(shù)本身。這是一種循環(huán)引用, 下圖更好地說明了這種循環(huán)關(guān)系。
圖1 循環(huán)關(guān)系
現(xiàn)在,通過new運(yùn)算符用函數(shù)(上面示例中為 person)創(chuàng)建對(duì)象時(shí),所獲得的對(duì)象將繼承 person.prototype 的屬性。在上圖,可以看到 person.prototype 對(duì)象有一個(gè)回指 person 函數(shù)的構(gòu)造函數(shù)屬性。這樣,每個(gè) person對(duì)象(從 person.prototype 繼承而來)都有一個(gè)回指 person 函數(shù)的構(gòu)造函數(shù)屬性。
我們可以用以下代碼來驗(yàn)證這種循環(huán)是否正確:
function person(name, age) {
this.name = name;
this.age = age;
}
person.prototype.getInfo = function() {
alert("My name is "+this.name+", and I have "+this.age+" years old");
}
var zhangchen = new person("zhangchen", 23);
alert(zhangchen.constructor == person.prototype.constructor); //output true
alert(zhangchen.constructor == person);// output true
alert(person.prototype.isPrototypeOf(zhangchen)); //output true
以上代碼中的對(duì)"isPrototypeOf()"方法的調(diào)用來自哪里呢?是來自person.prototype對(duì)象嗎?不對(duì),實(shí)際上,在 person.prototype 和 person 實(shí)例中還可以調(diào)用其他方法,比如 toString、toLocaleString 和 valueOf,但它們都不來自 person.prototype。而是來自于JavaScript 中的 Object.prototype ,它是所有原型的最終基礎(chǔ)原型。(Object.prototype 的原型是 null。)
在以上例中,zhangchen.prototype 是對(duì)象。它是通過調(diào)用 Object 構(gòu)造函數(shù)創(chuàng)建的(盡管它不可見)相當(dāng)于執(zhí)行子以下代碼:
zhangchen.prototype = new Object();
因此,正如 person實(shí)例繼承person.prototype 一樣,zhangchen.prototype 繼承 Object.prototype。這使得所有 zhangchen 實(shí)例也繼承了 Object.prototype 的方法和屬性。
原型鏈:每個(gè) JavaScript 對(duì)象都繼承一個(gè)原型鏈,而所有原型都終止于 Object.prototype。注意,這種繼承是活動(dòng)對(duì)象之間的繼承。它不同于繼承的常見概念,后者是指在聲明類時(shí)類之間的發(fā)生的繼承。因此,JavaScript 繼承動(dòng)態(tài)性更強(qiáng)。它使用簡單算法實(shí)現(xiàn)這一點(diǎn),如下所示:當(dāng)您嘗試訪問對(duì)象的屬性/方法時(shí),JavaScript 將檢查該屬性/方法是否是在該對(duì)象中定義的。如果不是,則檢查對(duì)象的原型。如果還不是,則檢查該對(duì)象的原型的原型,如此繼續(xù),一直檢查到 Object.prototype。下圖說明了此解析過程:
圖2 toString()方法的解析過程
從以上解析過程中,如果在對(duì)象中定義了屬性/方法 X,則該對(duì)象的原型中將隱藏同名的屬性/方法。例如,通過在 person.prototype 中定義 toString 方法,可以改寫 Object.prototype 的 toString 方法。
再看以下代碼:
function person(name, age) {
this.name = name;
this.age = age;
}
person.prototype.getInfo = function() {
alert("My name is "+this.name+", and I have "+this.age+" years old");
}
var zhangchen = new person("zhangchen", 23);
var luomi = new person("luomi", 23);
zhangchen.getInfo(); // output My name is zhangchen, and I have 23 years old;
luomi.getInfo(); // output My name is luomi, and I have 23 years old;
luomi.getInfo = function() {
alert("here can rewrite the function of getInfo!");
}
luomi.getInfo(); //here can rewrite the function of getInfo!
zhangchen.getInfo(); // output My name is zhangchen, and I have 23 years old;
從運(yùn)行結(jié)果可以看到,雖然person的每個(gè)實(shí)例都繼承了person.prototype中的方法,但是我們也可以在實(shí)例化的對(duì)象中重新定義原型對(duì)象中的方法,而且也不會(huì)影響到其它的實(shí)例!
以上是自己對(duì)原型及原型鏈繼承方式的認(rèn)識(shí),參考( JavaScript: 使用面向?qū)ο蟮募夹g(shù)創(chuàng)建高級(jí) Web 應(yīng)用程序),希望大家共同討論!
相關(guān)文章
前端編碼規(guī)范(3)JavaScript 開發(fā)規(guī)范
這篇文章主要介紹了前端編碼規(guī)范(3)JavaScript 開發(fā)規(guī)范,需要的朋友可以參考下2017-01-01解析js中獲得父窗口鏈接getParent方法以及各種打開窗口的方法
本篇文章是對(duì)js中獲得父窗口鏈接getParent方法以及各種打開窗口的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06javascript實(shí)現(xiàn)方法調(diào)用與方法觸發(fā)小結(jié)
這篇文章主要介紹了javascript實(shí)現(xiàn)方法調(diào)用與方法觸發(fā)小結(jié)的相關(guān)資料,需要的朋友可以參考下2016-03-03JavaScript關(guān)鍵字this的用法總結(jié)
這篇文章介紹了JavaScript關(guān)鍵字this的用法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06每個(gè)程序員都需要學(xué)習(xí) JavaScript 的7個(gè)理由小結(jié)
這篇文章主要介紹了每個(gè)程序員都需要學(xué)習(xí) JavaScript 的7個(gè)理由小結(jié),需要的朋友可以參考下2016-09-09