原型與原型鏈的理解

原型對象

javascript語言是一種面向對象的語言,它沒有"子類"和"父類"的概念,里面所有的數(shù)據類型都是對象,如何將這些對象聯(lián)系起來呢?
Brendan Eich在考慮設計繼承機制的時候,參考了C++和JAVA使用new命令,通過調用類的構造函數(shù)生成實例的方式,將new命令引入javascript。
C++的寫法是:

 ClassName *object = new ClassName(param);

Java的寫法是:

 Person person = new Person();

但是,javascript里面沒有“類”這個概念,那么,Brendan Eich決定直接在new后面跟一個構造函數(shù),來生成實例。
構造函數(shù)是什么?構造函數(shù)與其他函數(shù)唯一的區(qū)別在于調用方式不同。任何函數(shù)只要通過new來調用就可以作為構造函數(shù),它是用來創(chuàng)建特定類型的對象。
下面定義一個構造函數(shù)Female:

function Female(name){
     this.name = name;
    this.sex = 'female';  
 }

通過new命令來生成一個person實例:

var person1 = new Female("Summer")

這里,構造函數(shù)Female就是實例對象person1的原型?。?!Female里的this關鍵字就指的是person1這個對象!
new出來的person1對象此時已經和Female再無聯(lián)系了!也就是說每一個new出來的實例都有自己的屬性和方法的副本,是獨立的的!修改其中一個不會影響另一個!

var person1 = new Female("Summer");
var person2 = new Female("Lily");

person2.sex = 'male';

console.log(person1.sex)      // female
console.log(person2.sex)      // male

但是,我們希望構造函數(shù)中的sex屬性是一個共有屬性,那么此時用這樣的方法,每個實例中都有一個相同的sex屬性,會造成資源極大的浪費!
那么原型對象就即將登場了!Brendan Eich決定給每一個構造函數(shù)都設置一個prototype屬性,這個屬性就指向原型對象。其實原型對象就只是個普通對象,里面存放著所有實例對象需要共享的屬性和方法!所以,我們把需要共享的放到原型對象里,把那些不需要共享的屬性和方法存在在構造函數(shù)里!
那么上面的代碼可改寫如下:

function Person(name,age){
            this.name = name;
        }
        Person.prototype.sex = 'female';

        var person1 = new Person("Summer");
        var person2 = new Person("Lily");
        
        console.log(person1.sex)      // female
        console.log(person2.sex)      // female

        Person.prototype.sex = 'male';

        console.log(person1.sex)      // male
        console.log(person2.sex)      // male

可以看出,修改prototype屬性會影響它的所有實例的sex的值??!
實例一旦創(chuàng)建出來就會自動引用prototype對象的屬性和方法!所以實例對象的屬性和方法一般分為兩種:一種是自身的,一種是引用自prototype的。
具體實現(xiàn)是這樣的:
每當代碼讀取某個對象的某個屬性的時候,都會執(zhí)行一次搜索。首先從對象實例本身開始,如果在實例中找到了該屬性,則返回該屬性的值,如果沒有找到,則順著原型鏈指針向上,到原型對象中去找,如果如果找到就返回該屬性值。
這里要提一點,如果為對象實例添加了一個屬性與原型中同名,則該屬性會屏蔽掉原型中的同名屬性,不會去修改它!使用delete可以刪除實例中的屬性提到delete那要插一句~delete只能刪除對象下的屬性,不能刪除變量和參數(shù)!

原型鏈

事實上,js里完全依靠"原型鏈"(prototype chain)模式來實現(xiàn)繼承。
上面說完原型對象。下面說一說proto、prototype、constructor。

proto:事實上就是原型鏈指針??!
prototype:上面說到這個是指向原型對象的
constructor:每一個原型對象都包含一個指向構造函數(shù)的指針,就是constructor

繼承實現(xiàn)方式:

為了實現(xiàn)繼承,proto會指向上一層的原型對象,而上一層的結構依然類似,那么就利用proto一直指向Object的原型對象上!Object.prototype.__proto__ = null;表示到達最頂端。如此形成了原型鏈繼承。
大致總結一下就是:
1、Object是作為眾多new出來的實例的基類 function Object(){ [ native code ] }
2、Function是作為眾多function出來的函數(shù)的基類 function Function(){ [ native code ] }
3、構造函數(shù)的proto(包括Function.prototype和Object.prototype)都指向Function.prototype
4、原型對象的proto都指向Object.prototype
5、Object.prototype.proto指向null

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容