原型對象
javascript語言是一種面向?qū)ο蟮恼Z言,它沒有"子類"和"父類"的概念怀愧,里面所有的數(shù)據(jù)類型都是對象怔昨,如何將這些對象聯(lián)系起來呢?
Brendan Eich在考慮設(shè)計(jì)繼承機(jī)制的時候署穗,參考了C++和JAVA使用new命令寥裂,通過調(diào)用類的構(gòu)造函數(shù)生成實(shí)例的方式嵌洼,將new命令引入javascript。
C++的寫法是:
ClassName *object = new ClassName(param);
Java的寫法是:
Person person = new Person();
但是封恰,javascript里面沒有“類”這個概念麻养,那么,Brendan Eich決定直接在new后面跟一個構(gòu)造函數(shù)诺舔,來生成實(shí)例鳖昌。
構(gòu)造函數(shù)是什么?構(gòu)造函數(shù)與其他函數(shù)唯一的區(qū)別在于調(diào)用方式不同低飒。任何函數(shù)只要通過new來調(diào)用就可以作為構(gòu)造函數(shù)遗遵,它是用來創(chuàng)建特定類型的對象。
下面定義一個構(gòu)造函數(shù)Female:
function Female(name){
this.name = name;
this.sex = 'female';
}
通過new命令來生成一個person實(shí)例:
var person1 = new Female("Summer")
這里逸嘀,構(gòu)造函數(shù)Female就是實(shí)例對象person1的原型3狄!崭倘!Female里的this關(guān)鍵字就指的是person1這個對象翼岁!
new出來的person1對象此時已經(jīng)和Female再無聯(lián)系了!也就是說每一個new出來的實(shí)例都有自己的屬性和方法的副本司光,是獨(dú)立的的琅坡!修改其中一個不會影響另一個!
var person1 = new Female("Summer");
var person2 = new Female("Lily");
person2.sex = 'male';
console.log(person1.sex) // female
console.log(person2.sex) // male
但是残家,我們希望構(gòu)造函數(shù)中的sex屬性是一個共有屬性榆俺,那么此時用這樣的方法,每個實(shí)例中都有一個相同的sex屬性坞淮,會造成資源極大的浪費(fèi)茴晋!
那么原型對象就即將登場了!Brendan Eich決定給每一個構(gòu)造函數(shù)都設(shè)置一個prototype屬性回窘,這個屬性就指向原型對象诺擅。其實(shí)原型對象就只是個普通對象,里面存放著所有實(shí)例對象需要共享的屬性和方法啡直!所以烁涌,我們把需要共享的放到原型對象里,把那些不需要共享的屬性和方法存在在構(gòu)造函數(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屬性會影響它的所有實(shí)例的sex的值!舷丹!
實(shí)例一旦創(chuàng)建出來就會自動引用prototype對象的屬性和方法抒钱!所以實(shí)例對象的屬性和方法一般分為兩種:一種是自身的,一種是引用自prototype的。
具體實(shí)現(xiàn)是這樣的:
每當(dāng)代碼讀取某個對象的某個屬性的時候继效,都會執(zhí)行一次搜索症杏。首先從對象實(shí)例本身開始,如果在實(shí)例中找到了該屬性瑞信,則返回該屬性的值厉颤,如果沒有找到,則順著原型鏈指針向上凡简,到原型對象中去找逼友,如果如果找到就返回該屬性值。
這里要提一點(diǎn)秤涩,如果為對象實(shí)例添加了一個屬性與原型中同名帜乞,則該屬性會屏蔽掉原型中的同名屬性,不會去修改它筐眷!使用delete可以刪除實(shí)例中的屬性提到delete那要插一句~delete只能刪除對象下的屬性黎烈,不能刪除變量和參數(shù)!
原型鏈
事實(shí)上匀谣,js里完全依靠"原型鏈"(prototype chain)模式來實(shí)現(xiàn)繼承照棋。
上面說完原型對象。下面說一說proto武翎、prototype烈炭、constructor。
proto:事實(shí)上就是原型鏈指針1Χ瘛符隙!
prototype:上面說到這個是指向原型對象的
constructor:每一個原型對象都包含一個指向構(gòu)造函數(shù)的指針,就是constructor
繼承實(shí)現(xiàn)方式:
為了實(shí)現(xiàn)繼承垫毙,proto會指向上一層的原型對象霹疫,而上一層的結(jié)構(gòu)依然類似,那么就利用proto一直指向Object的原型對象上露久!Object.prototype.__proto__ = null
;表示到達(dá)最頂端更米。如此形成了原型鏈繼承欺栗。
大致總結(jié)一下就是:
1毫痕、Object是作為眾多new出來的實(shí)例的基類 function Object(){ [ native code ] }
2、Function是作為眾多function出來的函數(shù)的基類 function Function(){ [ native code ] }
3迟几、構(gòu)造函數(shù)的proto(包括Function.prototype和Object.prototype
)都指向Function.prototype
4消请、原型對象的proto都指向Object.prototype
5、Object.prototype.proto指向null