面試 | JS高級(jí)---原型到原型鏈(一看就懂)

面試 | JS高級(jí)---原型到原型鏈(一看就懂)

?

一個(gè)敲代碼的前端妹子?已關(guān)注

?0.4?2018.06.28 09:47?字?jǐn)?shù) 1383?閱讀 495評(píng)論 2喜歡 11

文中關(guān)于一些概念說了可能三到四邊,或者更多,希望是加深大家的印象,希望理解,重要的概念說三遍,只要你能理解,我啰嗦五次都愿意。

構(gòu)造函數(shù)創(chuàng)建對(duì)象

==========咱們先來一個(gè)栗子=======

function Person(name){//構(gòu)造函數(shù)? ? ? ? ? this.name=name; } Person.prototype.printName=function( ){//原型對(duì)象? ? ? ? ? ? alert(this.name); } var person1=new Person('ming');//實(shí)例化對(duì)象 console.log(person1.__proto__);//這里自己打印一下,印象更深刻 console.log(person1.constructor);//console.log(Person.prototype);//varperson2=new Person('Frank');

? (注意這里的大小寫)Person的實(shí)例person1中包含了name屬性,同時(shí)也自動(dòng)生成一個(gè)__proto__屬性,該屬性指向Person的prototype,可以訪問到prototype內(nèi)定義的printName方法,大概就? 是這個(gè)樣子的:每個(gè)JavaScript函數(shù)都有prototype屬性,這個(gè)屬性引用了一個(gè)對(duì)象,這個(gè)對(duì)象就是**原型對(duì)象**。**原型對(duì)象初始化的時(shí)候是空的**,我們可以在里面自定義任何屬性和方法,這些方法和屬性都將被該**構(gòu)造函數(shù)**所創(chuàng)建的對(duì)象**繼承**。(下一篇我會(huì)更詳細(xì)的介紹原型,很暴力的)

實(shí)例是通過構(gòu)造函數(shù)創(chuàng)建的。實(shí)例一創(chuàng)造出來就具有constructor屬性(指向構(gòu)造函數(shù))和proto屬性(指向原型對(duì)象),

構(gòu)造函數(shù)中有一個(gè)prototype屬性,這個(gè)屬性是一個(gè)指針,指向它的原型對(duì)象。

原型對(duì)象內(nèi)部也有一個(gè)指針(constructor屬性)指向構(gòu)造函數(shù):Person.prototype.constructor = Person;

實(shí)例可以訪問原型對(duì)象上定義的屬性和方法。

在這里person1和person2就是實(shí)例,prototype是他們的原型對(duì)象。

//========再來一個(gè)栗子===========

function Animal(name){ //構(gòu)造函數(shù)

this.name = name;//設(shè)置對(duì)象屬性}Animal.prototype.behavior =function(){console.log("this is a "+this.name);}varDog =newAnimal("dog");

var Cat = new Animal("cat");

Dog.behavior();//通過Dog對(duì)象直接調(diào)用behavior方法

Cat.behavior(); //"this is a cat"

console.log(Dog.behavior==Cat.behavior);// true;

//總結(jié):構(gòu)造函數(shù)的prototype上定義的方法確實(shí)可以通過對(duì)象直接調(diào)用到,而且代碼是共享的。prototype屬性指向Animal對(duì)象。

================= 開始正題 ==================

-1-Prototype:

每個(gè)函數(shù)都有一個(gè)prototype屬性,也只有函數(shù)有該屬性。

function Person(){ }

Person.prototype.name = 'name';

var person1 = new Person();

var person2 = new Person();

console.log(person1.name) // name

console.log(person2.name) //name

問:那這個(gè)函數(shù)的prototype屬性到底指向的是什么呢?是這個(gè)函數(shù)的原型嗎?

| |

| |

總結(jié):函數(shù)的prototype屬性指向了一個(gè)對(duì)象,這個(gè)對(duì)象正是調(diào)用該構(gòu)造函數(shù)而創(chuàng)建的實(shí)例的原型,也就是這個(gè)例子中的person1和person2的原型。

問:什么是原型?每一個(gè)JavaScript對(duì)象(null除外)在創(chuàng)建的時(shí)候就會(huì)與之關(guān)聯(lián)另一個(gè)對(duì)象,這個(gè)對(duì)象就是我們所說的原型,每一個(gè)對(duì)象都會(huì)從原型”繼承”屬性。

-2-proto:

怎么表示實(shí)例與實(shí)例原型,也就是person和Person.prototype之間的關(guān)系呢,這時(shí)候我們就要講到第二個(gè)屬性:

proto。每一個(gè)JavaScript對(duì)象(除了null)都具有的一個(gè)屬性,叫proto,這個(gè)屬性會(huì)指向該對(duì)象的原型。

function Person( ){

}

var person = new Person();

console.log(person.proto?=== Person.prototype); //true

問:既然實(shí)例對(duì)象和構(gòu)造函數(shù)都可以指向原型,那么原型是否有屬性指向構(gòu)造函數(shù)或者實(shí)例呢?

-3- constructor

沒有指向?qū)嵗?,因?yàn)橐粋€(gè)構(gòu)造函數(shù)可以生成多個(gè)實(shí)例,但是原型指向構(gòu)造函數(shù)是有的,這就要講到第三個(gè)屬性:construcotr,每個(gè)原型都有一個(gè)constructor屬性指向關(guān)聯(lián)的構(gòu)造函數(shù)

為了驗(yàn)證這一點(diǎn),我們可以嘗試:

function Person() {

}

console.log(Person === Person.prototype.constructor); //true

精華----綜上總結(jié):(看清大下寫)

function Person() { //構(gòu)造函數(shù)

}

var person = new Person(); //實(shí)例對(duì)象

console.log(person.proto?== Person.prototype) //true

console.log(Person.prototype.constructor == Person) // true// 順便學(xué)習(xí)一個(gè)ES5的方法,可以獲得對(duì)象的原型console.log(Object.getPrototypeOf(person) === Person.prototype) //true

實(shí)例與原型

當(dāng)讀取實(shí)例的屬性時(shí),如果找不到,就會(huì)查找與對(duì)象關(guān)聯(lián)的原型中的屬性,如果還查不到,就去找原型的原型,一直找到最頂層為止。

======舉個(gè)例子:=========

function Person() {

}

Person.prototype.name = 'name';

var person = new Person();

person.name = 'name of this person';

console.log(person.name) // name of this person

delete person.name;

console.log(person.name) // name

我設(shè)置了person的name屬性,所以我可以讀取到為’name of this person’,當(dāng)我刪除了person的name屬性時(shí),讀取person.name,從person中找不到就會(huì)從person的原型也就是person.proto?== Person.prototype中查找,幸運(yùn)的是我們找到了為’name’,但是萬一還沒有找到呢?哪原型的原型又是什么呢?

在前面,我說過原型也是一個(gè)對(duì)象,既然是對(duì)象,我就可以用最原始的方式創(chuàng)建它,那就是

var obj = new Object();//字面兩創(chuàng)建對(duì)象new一個(gè)

obj.name = 'name';

console.log(obj.name) // name

所以原型對(duì)象是通過Object構(gòu)造函數(shù)生成的,結(jié)合之前所講,實(shí)例的proto指向構(gòu)造函數(shù)的prototype,

原型鏈

問:Object.prototype的原型是什么?

null,嗯,對(duì)就是null,所以查到Object.prototype就可以停止查找了

補(bǔ)充,最后,補(bǔ)充和糾正本文中一些不嚴(yán)謹(jǐn)?shù)牡胤剑?/b>

首先是constructor,

function Person() {

}

var person = new Person();

console.log(person.constructor === Person); // true

當(dāng)獲取person.constructor時(shí),其實(shí)person中并沒有constructor屬性,當(dāng)不能讀取到constructor屬性時(shí),會(huì)先從person的原型也就是Person.prototype中讀取,正好原型中有該屬性,所以

person.constructor === Person.prototype.constructor

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容