原型與原型鏈都還沒(méi)有弄明白javascript算是白學(xué)了

作者:極客小俊
我不用拼過(guò)聰明人,我只需要拼過(guò)那些懶人 我就一定會(huì)超越大部分人!
原創(chuàng)技術(shù)文章

javascript2.png
首先我們了解一下普通對(duì)象 與 函數(shù)對(duì)象

我們?cè)趯W(xué)習(xí)原型之前首先了解一下javascript當(dāng)中的 普通對(duì)象函數(shù)對(duì)象,

如圖1

在這里插入圖片描述
  • 普通對(duì)象:
    • 最普通的對(duì)象:具有_ _ proto_ _這個(gè)屬性它(指向其原型鏈),注意: 普通的對(duì)象是沒(méi)有prototype這個(gè)屬性的! 如果你調(diào)用必然返回undefined
    • 原型對(duì)象: 我們會(huì)在下面繼續(xù)說(shuō)明!

javascript中哪些情況屬于普通對(duì)象 如下代碼:

//普通對(duì)象  
function Test() {

}
var obj1 = new Test();
var obj2 = new Object();
var obj3 = {};


console.log(typeof obj1);    //Object
console.log(typeof obj2);    //Object
console.log(typeof obj3);    //Object
  • 函數(shù)對(duì)象

    • 凡是用Function()創(chuàng)建的都是函數(shù)對(duì)象。 比如:自定義函數(shù), 事件函數(shù) 系統(tǒng)的Object、Array、Date、String、RegEx 以上都屬于 函數(shù)對(duì)象

      ==小提示:== 以上的都是Function的實(shí)例對(duì)象, 那么也只有實(shí)例才會(huì)有_ _ proto_ _ 這個(gè)屬性
      
       ==注意:==  這里的Function是比較特殊的函數(shù)對(duì)象, 因?yàn)镕unction.prototype本身它應(yīng)該指向是原型對(duì)象, 但Function的prototype卻是函數(shù)對(duì)象  上圖已經(jīng)有說(shuō)明!
      

javascript中哪些情況屬于函數(shù)對(duì)象 如下代碼:

//函數(shù)對(duì)象  

function F1(){
    
}

var F2 = function(){
    
}
var F3 = function(a,b){
    
}


window.onload=function () {
    var div1=document.getElementById('div1');
    div1.onclick=function () {
        alert(1);
    }
    console.log(typeof div1.onclick);   //function  
}

 
console.log(typeof F1);       //function  
console.log(typeof F2);       //function  
console.log(typeof F3);       //function  

console.log(typeof Object);   //function  
console.log(typeof Array);    //function  
console.log(typeof String);   //function  
console.log(typeof Date);     //function  
console.log(typeof RegEx);    //function  
console.log(typeof Function); //function  

函數(shù)對(duì)象都是Function的實(shí)例對(duì)象

就如同Array是通過(guò)Function創(chuàng)建出來(lái)的。

因?yàn)锳rray是Function的實(shí)例,是實(shí)例就會(huì)有._ _ proto_ _ 這個(gè)屬性, 從上面的流程圖上看 一個(gè)函數(shù)對(duì)象的_ _ proto_ _屬性值是: ? () { [native code] }

而特殊的Function.prototype的值也是一個(gè): ? () { [native code] }

所以我們可以推斷出一個(gè)條件: 函數(shù)對(duì)象._ _ proto_ _ === Function.prototype 是成立的! 返回true

由此引出下面判斷條件:

Array._ _proto_ _  == Function.prototype     //true

String._ _proto_ _ == Function.prototype     //true

RegExp._ _proto_ _== Function.prototype     //true

Date._ _proto_ _  == Function.prototype     //true
? () { [native code] } 是什么?

native code 的意思是它是程序自帶的,是二進(jìn)制編譯的無(wú)法顯示出來(lái)代碼, native code是本地代碼, 這里我們就簡(jiǎn)單的解釋一下即可!

以上內(nèi)容作為學(xué)習(xí)原型之前的鋪墊了解即可!! 接下來(lái)我們就慢慢的拆解圖1的細(xì)節(jié)內(nèi)容!!


引出兩個(gè)問(wèn)題

問(wèn)題1 性能方面

如果創(chuàng)建一個(gè)對(duì)象 在內(nèi)存的堆區(qū)中就會(huì)開(kāi)辟一個(gè)空間來(lái)保存對(duì)象,如果每個(gè)對(duì)象里面有相同的方法也會(huì)被創(chuàng)建出來(lái)

這樣就存在一個(gè)問(wèn)題,就是公共的方法或者屬性會(huì)存在內(nèi)存當(dāng)中n份.. , 大量的占用了內(nèi)存開(kāi)銷(xiāo)!

如圖2

每一個(gè)對(duì)象都生成了同樣的say()方法, 這種代碼中如果每個(gè)對(duì)象都有公共一樣的方法 就顯得很占據(jù)內(nèi)存空間!

在這里插入圖片描述

上圖的代碼如下

function Person(name,age){
    this.name=name;
    this,age=age;
    this.say=function () {
        console('輸出結(jié)果');
    }
}

var obj1=new Person();
var obj2=new Person();
var obj3=new Person();
var obj4=new Person();
var obj5=new Person();

問(wèn)題2 屬性 方法 不能共享!

有時(shí)候我們希望一個(gè)方法能夠被多個(gè)相同對(duì)象類(lèi)型都可以公共的進(jìn)行使用!

例如: 定義一個(gè)數(shù)組私有方法, 而另外一個(gè)數(shù)組對(duì)象是不能訪問(wèn)這個(gè)私有方法的

代碼案例:

var arr=[5,5,10];
//arr數(shù)組對(duì)象的sum方法
arr.sum=function () {
    var result=0;
    for(var i=0;i<this.length;i++){
        result+=this[i];
    }
    return result;
}

console.log(arr.sum());  //結(jié)果: 20

var arr2=[10,10,10];
console.log(arr2.sum()); //結(jié)果: Uncaught TypeError: arr2.sum is not a function

解答: 這里報(bào)錯(cuò)是因?yàn)?arr2 這個(gè)數(shù)組對(duì)象 根本就不存在sum() 這個(gè)方法, 它是屬于arr數(shù)組對(duì)象私有的一個(gè)方法!

所以有時(shí)候我們希望一個(gè)方法能夠被多個(gè)相同對(duì)象類(lèi)型都可以公共的來(lái)使用!

以上兩個(gè)問(wèn)題 , 問(wèn)題1是性能優(yōu)化不足,問(wèn)題2是私有方法不能被相同類(lèi)型的對(duì)象調(diào)用 , 所以解決上述問(wèn)題方法或?qū)傩圆荒芄蚕淼霓k法 就要用到: 原型 [提高性能] 也就是通常說(shuō)的: 原型模式

接下來(lái)我們就來(lái)探討一下原型是什么!


原型對(duì)象是什么!

根據(jù)圖1 函數(shù)對(duì)象都有一個(gè)prototype屬性指向的是一個(gè)原型對(duì)象, 那么我們可以推出以下概念:

每創(chuàng)建一個(gè)函數(shù)都會(huì)有一個(gè)prototype屬性,這個(gè)屬性是一個(gè)指針,指向一個(gè)對(duì)象(原型對(duì)象)

原型對(duì)象,也就是(構(gòu)造函數(shù).prototype), 當(dāng)中含有一個(gè)constructor 屬性 這個(gè)屬性(指向的就是當(dāng)前原型對(duì)象的構(gòu)造函數(shù))

如下圖:

在這里插入圖片描述

原型對(duì)象作用:是包含特定類(lèi)型的所有實(shí)例共享的屬性和方法, 就是說(shuō)你把屬性和方法定義在原型對(duì)象里面之后,那么這個(gè)類(lèi)型的實(shí)例就都會(huì)共享這些屬性和方法!

原型對(duì)象優(yōu)點(diǎn): 就是可以讓所有實(shí)例對(duì)象共享它所包含的屬性和方法。

原型對(duì)象的語(yǔ)法基礎(chǔ)

要特定類(lèi)型的所有實(shí)例都共享的屬性和方法, 就要把它們定義在原型對(duì)象的下面!

原型: 要使用==prototype==這個(gè)關(guān)鍵字, 要寫(xiě)在構(gòu)造函數(shù)的下面:

//語(yǔ)法如下

構(gòu)造函數(shù)名.prototype.屬性=值;

構(gòu)造函數(shù)名.prototype.方法=function(){
        ..代碼段..
} 

如下圖: 所以用: 構(gòu)造函數(shù)名.prototype 你就可以把屬性和方法定義在原型對(duì)象當(dāng)中

在這里插入圖片描述

案例代碼:

function createPerson(name,age) {
    this.name=name;
    this,age=age;
}

createPerson.prototype.say=function () {
    console.log('我的名字叫'+this.name);
}

var a=new createPerson('張三','33');
var b=new createPerson('李四','55');
var c=new createPerson('王武','66');

a.say();
b.say();
c.say();

為了方便理解 我畫(huà)了一張圖, 以上代碼的流程圖分析如下圖:

在這里插入圖片描述
特殊的Function.prototype

Function.prototype是個(gè)例外,為什么說(shuō)它是一個(gè)例外呢? 按道理來(lái)說(shuō)它這里獲取出來(lái)的應(yīng)該是一個(gè)原型對(duì)象,但卻是一個(gè)函數(shù)對(duì)象,

作為一個(gè)函數(shù)對(duì)象,它又沒(méi)有prototype屬性。 從圖1中就可以看出來(lái)這個(gè)道理!

你用Function.prototype 獲取出來(lái)是一個(gè): ? () { [native code] } 這個(gè)東西是什么上面已經(jīng)解釋過(guò)了!

如下圖:

在這里插入圖片描述
原型知識(shí)點(diǎn)

為了節(jié)省內(nèi)存,我們把對(duì)象的方法都放在原型里面。為什么呢?

因?yàn)楦膶?xiě)對(duì)象下面公用的方法或者屬性、讓公用的方法或者屬性在內(nèi)存中只存在一份

在我們通過(guò)new實(shí)例化對(duì)象的時(shí)候,在內(nèi)存中,會(huì)自動(dòng)拷貝構(gòu)造函數(shù)中的所有屬性和方法,用來(lái)給實(shí)例對(duì)象賦值,而不管我們實(shí)例化多少次,原型里面的屬性和方法只生成一次,所以會(huì)節(jié)省內(nèi)存。

普通定義方式與原型定義的優(yōu)先級(jí)高低

如下代碼:

function createPerson(name,age) {
            this.name=name;
            this,age=age;
        }

createPerson.prototype.say=function () {
    console.log('我的名字叫'+this.name);
}

var a=new createPerson('張三','33');
var b=new createPerson('李四','55');
var c=new createPerson('王武','66');

a.say();
b.say();
c.say();

//普通定義的優(yōu)先級(jí)高于原型prototype
c.say=function(){
    console.log('輸出ok');
}
        
c.say();

所以以上的普通定義的方式要比原型定義的方式的優(yōu)先級(jí)高!,但這并不是把原型覆蓋了 只是優(yōu)先調(diào)用普通定義的方法

如圖:

在這里插入圖片描述

原型的中的 _ _ proto_ _

首先回顧一下, 實(shí)例化new的時(shí)候,系統(tǒng)會(huì)在內(nèi)存中創(chuàng)建了一個(gè)空的對(duì)象,就像是這樣 var p = {} , 拷貝構(gòu)造函數(shù)中的屬性和方法到空對(duì)象中。

重點(diǎn)的是: 每個(gè)實(shí)例化對(duì)象都會(huì)有一個(gè) _ _ proto_ _ 屬性, 這個(gè)屬性是自動(dòng)生成的, _ _ proto_ _ 屬性指向類(lèi)的原型對(duì)象。

構(gòu)造函數(shù)、實(shí)例化對(duì)象、原型對(duì)象的之間的關(guān)系

先來(lái)看一段代碼案例

function createPerson(name,age) {
    this.name=name;
    this,age=age;
}

createPerson.prototype.say=function () {
    console.log('我的名字叫'+this.name);
}

var obj=new createPerson('張三','33');

console.log(obj.__proto__);              //實(shí)例化obj的__proto__屬性 可以獲取到原型對(duì)象
console.log(createPerson.prototype);     //構(gòu)造函數(shù)的prototype屬性  也可以獲取到原型對(duì)象
console.log(obj.__proto__.constructor);  //原型對(duì)象中的constructor又可以獲取到構(gòu)造函數(shù)

構(gòu)造函數(shù)、實(shí)例化對(duì)象、原型對(duì)象的基本關(guān)系圖分析
在這里插入圖片描述

當(dāng)然你也可以通過(guò) 實(shí)例化對(duì)象的_ _ proto_ _屬性 和 構(gòu)造函數(shù)的prototype屬性進(jìn)行比較可以驗(yàn)證結(jié)果, 我們可以通過(guò)打印來(lái)驗(yàn)證

console.log(實(shí)例化對(duì)象._ _proto_ _ === 構(gòu)造函數(shù).prototype);     //true

定義在實(shí)例和定義在原型下的區(qū)別總結(jié):

先看一段代碼案例:

function Test(){
    
}
//定義屬性
Test.prototype.name = "張三";  
Test.prototype.age =  33;
//定義方法
Test.prototype.getAge = function(){  
    return this.age;  
}  
  
var t1 = new Test();  
var t2 = new Test();
var t3 = new Test();  
t3.name = "李四";  

console.log(t1.name); // 張三 來(lái)自原型  
console.log(t2.name); // 張三 來(lái)自原型  
console.log(t3.name); // 李四 來(lái)自實(shí)例  

//打印實(shí)例看下圖結(jié)果
console.log(t1);
console.log(t2);
console.log(t3);

在這里插入圖片描述

以上圖就解釋了為什么定義在原型中 屬性和方法是公用的, 而單獨(dú)定義在實(shí)例中是屬于獨(dú)立的屬性和方法不共有!

所以 我們也推斷出 在實(shí)例中定義屬性和方法 會(huì)覆蓋 或者說(shuō) 會(huì)實(shí)現(xiàn)調(diào)用實(shí)例中定義的屬性和方法 如果沒(méi)有才會(huì)到原型中去尋找! 這里其實(shí)就是我們一會(huì)要講到的原型鏈!

_ _ proto_ _與 prototype的詳細(xì)認(rèn)識(shí)

1.所有的引用類(lèi)型,比如數(shù)組、對(duì)象、都有一個(gè)_ _ proto_ _屬性(也叫==隱式原型==,它來(lái)指向自己的原型對(duì)象)

重點(diǎn)再次提醒: 所有的對(duì)象引用 都有_ _ proto_ _ 這個(gè)屬性! 記住了!

通過(guò)下面的測(cè)試我們不難發(fā)現(xiàn),其中它們賦值的引用對(duì)象中 打印出來(lái)看到都有一個(gè) _ _ proto_ _的屬性 都是指向自己的原型對(duì)象

代碼如下:

function createPerson(name,age) {
     this.name=name;
     this,age=age;
}
createPerson.prototype.say=function () {
    console.log('我的名字叫'+this.name);
}
var obj=new createPerson('測(cè)試','33');

//對(duì)象引用打印
console.log(obj);


var arr=[1,2,3];
//數(shù)組引用的打印
console.log(arr);

var arr2=new Array(2,2,2);
//數(shù)組引用的打印
console.log(arr2);


**2.再一次重點(diǎn)注意: 所有引用類(lèi)型,它的_ _ proto_ _屬性指向這個(gè)引用本身的原型對(duì)象 而構(gòu)造函數(shù)的prototype屬性的值也就是指向的原型對(duì)象 **

所以在各自相應(yīng)引用類(lèi)型的_ _ proto_ _屬性 和 構(gòu)造函數(shù)的 prototype屬性 彼此它們兩個(gè)是相等的! 上面的圖中也可以表明這一點(diǎn)!

_ _ proto_ _屬性 和 構(gòu)造函數(shù)的 prototype屬性比較, 案例代碼如下:

//案例1
function createPerson(name,age) {
    this.name=name;
    this,age=age;
}
createPerson.prototype.say=function () {
    console.log('我的名字叫'+this.name);
}

var obj=new createPerson('張三','33');

console.log(obj.__proto__);            //打印出obj對(duì)象引用的原型對(duì)象  
console.log(createPerson.prototype);   //打印出createPerson構(gòu)造函數(shù)的原型對(duì)象
console.log(obj.__proto__===createPerson.prototype);  //而且它們是相等的,指向同一個(gè)原型對(duì)象

//案例2
var arr=new Array(2,2,2);
console.log(arr.__proto__);
console.log(Array.prototype);
console.log(arr.__proto__ === Array.prototype);

3.所有的構(gòu)造函數(shù) 或者 普通函數(shù)都有一個(gè)prototype屬性 (這也叫顯式原型,它也指向自己的原型對(duì)象)。

案例代碼:

//普通函數(shù)
function Test() {

}
//打印普通函數(shù)的prototype屬性
console.log(Test.prototype);


//構(gòu)造函數(shù)
function createPerson(name,age) {
     this.name=name;
     this,age=age;
}
createPerson.prototype.say=function () {
    console.log('我的名字叫'+this.name);
}

console.log(createPerson.prototype);

圖解如下:

在這里插入圖片描述
_ _proto _ _和 prototype區(qū)別

==prototype==是每個(gè)函數(shù)都會(huì)具備的一個(gè)屬性,它是一個(gè)指針,指向原型對(duì)象,只有普通函數(shù)構(gòu)造函數(shù)才有。

==_ _ proto_ ==屬性 是主流瀏覽器上在除null對(duì)象以外的每個(gè)引用對(duì)象上都支持存在的一個(gè)屬性,它能夠指向當(dāng)前該引用對(duì)象的:原型對(duì)象
其實(shí)==
_ proto_ _== 就是用來(lái)將引用對(duì)象與原型相連的屬性

小結(jié): 一個(gè)只有函數(shù)才有的屬性(prototype),一個(gè)是引用對(duì)象才有的屬性(_ _ proto_ _ ),

注意: 你用一個(gè)函數(shù)去調(diào)用屬性(_ _ proto_ _ ), 會(huì)得到一個(gè): ? () { [native code] }

原型中批量添加屬性與方法

使用==prototype==這個(gè)關(guān)鍵字, 要批量的把屬性和方法寫(xiě)入原型 就在構(gòu)造函數(shù)的下面寫(xiě)一個(gè)JSON格式 如下代碼, 這樣比單一的一個(gè)個(gè)寫(xiě)方便!

//語(yǔ)法
構(gòu)造函數(shù).prototype={
    屬性名: 值,
    方法名:function(){
        //方法體...   這里的this是什么要看執(zhí)行的時(shí)候誰(shuí)調(diào)用了這個(gè)函數(shù)
    },
    方法名:function(){
       //方法體...   這里的this是什么要看執(zhí)行的時(shí)候誰(shuí)調(diào)用了這個(gè)函數(shù)
    }
}

案例代碼:

 createPerson.prototype={
     aaa:123,
     // prototype對(duì)象里面又有其他的屬性
     showName:function(){
         //this是什么要看執(zhí)行的時(shí)候誰(shuí)調(diào)用了這個(gè)函數(shù)
         console.log("我的名字叫:"+this.name);
     },
     showAge:function(){
         //this是什么要看執(zhí)行的時(shí)候誰(shuí)調(diào)用了這個(gè)函數(shù)
         console.log("我的年齡是:"+this.age);
     }
 }

function createPerson(name,age) {
    this.name=name;
    this.age=age;
}
var obj= new createPerson('張三','33');
console.log(obj);
obj.showName();
obj.showAge();
console.log(obj.aaa);

以上原型代碼 圖解

在這里插入圖片描述

原型注意事項(xiàng)

==<code>重點(diǎn)注意</code>==

如果是自定義構(gòu)造函數(shù),并且使用{ }這種方式批量的在prototype中定義屬性和方法, 會(huì)改變?cè)椭衏onstructor對(duì)構(gòu)造函數(shù)的指向!

==也就是說(shuō)使用{ }這種方式批量在prototype中定義屬性和方法, 那么constructor的指向就是一個(gè)函數(shù)對(duì)象==

測(cè)試代碼如下

function createPerson(name,age) {
    this.name=name;
    this,age=age;
}

/* createPerson.prototype.say=function(){
      console.log('我的名字叫'+this.name);
}*/

createPerson.prototype={
    say:function () {
        console.log('我的名字叫'+this.name);
    }
}

var obj=new createPerson('張三','33');
console.log(obj.__proto__);

在控制臺(tái)輸出會(huì)看到 _ _proto _ _的值, constructor這個(gè)屬性就沒(méi)有了!

在這里插入圖片描述
console.log(createPerson.prototype.constructor);   //返回   ? Object() { [native code] }
原型基本小結(jié)
  1. 讓相同方法在內(nèi)存中存在一份
  2. 原型定義方式要比普通定義方式的優(yōu)先級(jí)要低
  3. 在項(xiàng)目當(dāng)中公共相同的屬性和方法可以加載在原型上
原型鏈 核心原理

首先這里要提出一點(diǎn)的是 在JS中實(shí)現(xiàn)繼承主要是依靠原型鏈來(lái)實(shí)現(xiàn)! ,所以我們才需要學(xué)習(xí)原型鏈的原理!

原型鏈核心概念

原型鏈: 當(dāng)試圖調(diào)用或想得到一個(gè)對(duì)象實(shí)例中的屬性 或 方法時(shí),如果這個(gè)對(duì)象本身不存在這個(gè)屬性 或 方法 也就是說(shuō)構(gòu)造函數(shù)中沒(méi)有定義你想要的屬性或方法,那么就會(huì)通過(guò)構(gòu)造函數(shù)的prototype屬性到原型中去 尋找這個(gè)屬性 或者 方法 ==(也就是它的構(gòu)造函數(shù)的’prototype’屬性會(huì)到原型對(duì)象中去尋找) , 如果有就返回,如果沒(méi)有就會(huì)到頂層的Object去找 , 如果有就返回, 如果還是找不到就返回undefined!==

==原型鏈流程圖==

在這里插入圖片描述

上圖可以用以下例子來(lái)說(shuō)明:當(dāng)構(gòu)造函數(shù) Test 存在 getName 這個(gè)方法時(shí),就不用到構(gòu)造函數(shù)的原型當(dāng)中去找 getName這個(gè)方法;反之,就到構(gòu)造函數(shù)的原型當(dāng)中去找 getName這個(gè)方法;如果構(gòu)造函數(shù)的原型中也不存在 getName這個(gè)方法時(shí),就要到頂層對(duì)象的原型中去找 getName這個(gè)方法。

上圖測(cè)試案例代碼如下:

function Test(name){
    this.name=name;
    this.getName=function(){
        return this.name+"我在構(gòu)造函數(shù)中"; 
    }
}
Test.prototype.getName=function(){
    return this.name+"我在原型對(duì)象中";
}
Object.prototype.getName=function(){
    return this.name+"我在頂層對(duì)象中";
}
var t1=new Test('小紅');

console.log(t1.getName());

原型鏈案例代碼2 如下:

Array.prototype.aaa=123;    //把這個(gè)自定義屬性定義到原型對(duì)象下
var arr=new Array(1,2,3);
console.log(arr.aaa);
console.log(Array.prototype);

var arr2=['重慶','上海','北京'];
console.log(arr2.aaa);

如下圖:

在這里插入圖片描述

==小結(jié)==: arr 和 arr2都能夠找到aaa這個(gè)屬性, 并且這個(gè)屬性是數(shù)組原型對(duì)象下的屬性,是公共的

只要是數(shù)組就可以調(diào)用這個(gè)屬性, 同理方法也是一樣,

所以創(chuàng)建很多很多個(gè)相同類(lèi)型對(duì)象的時(shí)候, 創(chuàng)建出來(lái)的每一個(gè)對(duì)象,如果里面都有一些公共的方法,這樣就會(huì)占用很多的資源,

而通過(guò)原型來(lái)實(shí)現(xiàn)的話,只需要在構(gòu)造函數(shù)里面給屬性賦值,而把方法寫(xiě)在prototype屬性,當(dāng)然屬性也是可以寫(xiě)在原型當(dāng)中的,

這樣每個(gè)對(duì)象引用都可以使用prototype屬性里面的方法 或 屬性,并且節(jié)省了不少的資源

這就是我們?yōu)槭裁匆褂迷偷脑?


原型鏈總體結(jié)構(gòu)圖解小結(jié)

當(dāng)試圖調(diào)用或想得到一個(gè)對(duì)象實(shí)例中的屬性 或 方法時(shí),如果這個(gè)對(duì)象本身不存在這個(gè)屬性 或 方法 那么就會(huì)通過(guò)構(gòu)造函數(shù)的prototype屬性到原型中去 尋找這個(gè)屬性 或者 方法 ==如果有就返回,如果沒(méi)有就會(huì)到頂層的Object去找 , 如果有就返回, 如果還是找不到就返回undefined!==

但又因?yàn)闃?gòu)造函數(shù)中的prototype屬性值本身又是一個(gè)對(duì)象(原型對(duì)象), 所以這里它也有一個(gè)_ _ proto_ _ 屬性 , 就可以向上繼續(xù)獲取_ _ _ proto_ _屬性 , 那么這里獲取出來(lái)的就是頂層的Object對(duì)象

如下圖:

在這里插入圖片描述

小結(jié):

當(dāng)obj調(diào)用test()方法,JS發(fā)現(xiàn)Fn中沒(méi)有這個(gè)方法,于是它就去Fn.prototype中去找,發(fā)現(xiàn)還是沒(méi)有這個(gè)方法,然后就去Object.prototype中去找,找到了,就調(diào)用Object.prototype中的test()方法。

這就是原型鏈查找,而則一層一層的鏈接的關(guān)系就是:原型鏈。

obj能夠調(diào)用Object.prototype中的方法正是因?yàn)榇嬖谠玩滉P(guān)系的機(jī)制!

另外,在使用原型的時(shí)候,一般推薦將需要擴(kuò)展的方法寫(xiě)在 構(gòu)造函數(shù).prototype屬性中,

而不要寫(xiě)在: 構(gòu)造函數(shù).prototype._ _ proto _ _中, 因?yàn)檫@里也就是Object頂層對(duì)象,定義到這里的屬性和方法 所有JS對(duì)象都可以調(diào)用,在這里面定義多了就會(huì)影響整體性能,所以不建議定義到這里!

end.jpg
bilibili_gif.gif

如果我的博客對(duì)你有幫助、如果你喜歡我的博客內(nèi)容,請(qǐng) “點(diǎn)贊” “評(píng)論” “收藏” 一鍵三連哦!


如果以上內(nèi)容有任何錯(cuò)誤或者不準(zhǔn)確的地方,歡迎在下面 ?? 留個(gè)言指出、或者你有更好的想法,歡迎一起交流學(xué)習(xí)

最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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