JavaScript原型和原型鏈( prototype 與 __proto__ )


一、函數對象

 

  1. 所有引用類型(函數、數組、對象)都擁有__proto__屬性(隱式原型)

  2. 所有函數擁有 prototype 屬性(顯式原型)(僅限函數)

  3. 原型對象:擁有 prototype 屬性的對象,在定義函數時就被創建

 

關於 prototype__proto__

  • js中所有的函數都有一個 prototype 屬性,該屬性引用了一個對象,即原型對象,也簡稱原型
  • js對象有一個__proto__屬性,指向它的構造函數的prototype屬性
  • 對象.__proto__===函數.prototype;
var a = new A;
//a 類型:對象
//A 類型:函數

var Object = new Function();
//var 對象 = new 函數;

Object.__proto__ === Function.prototype;
//對象.__proto__ === 函數.prototype;

Function.__proto__ === Function.prototype;
//因為 Function 也是 Object

 

 

二、構造函數

 

 

1、什么是構造函數?

 

任何一個函數,只要被 new 操作符使用,就可以是一個構造函數(構造函數建議以大寫開頭)

另外,在 JavaScript 的內置對象中,所有的函數對象都是 Function 構造函數的實例,比如:Object、Array等

//創建構造函數
function Demo(name){
    this.name= name;
}
Demo.prototype = {
    alert(){
        alert(this.name);
    }
}
//創建實例
var a = new Demo("ming");
a.print = function(){
    console.log(this.name);
    console.log(this);  //Person對象
}
a.print();  //控制台內容如下
a.alert();  //彈出ming
  • print()方法是a實例本身具有的方法,所以 a.print() 打印 ming

     alert()不屬於a實例的方法,屬於構造函數的方法,a.alert() 也會打印 ming,因為實例繼承構造函數的方法

  • 實例a的隱式原型指向它構造函數的顯式原型,指向的意思是恆等於

a.__proto__ === Demo.prototype
  • 當調用某種方法或查找某種屬性時,首先會在自身調用和查找,如果自身並沒有該屬性或方法,則會去它的__proto__屬性中調用查找,也就是它構造函數的 prototype 中調用查找。

 

 

三、原型和原型鏈

 

1、什么是原型?

每個函數都具有 prototype 屬性,它被默認成一個對象,即原型對象

Function.prototype.a = "a";
Object.prototype.b = "b";
function Person(){}
console.log(Person);    //function Person()
let p = new Person();
console.log(p);         //Person {} 對象
console.log(p.a);       //undefined
console.log(p.b);       //b

 

2、什么是原型鏈?

當對象使用屬性時,先在自身找,有就直接用,沒有就沿着__proto__這條鏈往上找,直到 Object 原型的位置,有就返回相應的值,沒有就返回 underfined。

由於 p 是 Person() 的實例,是一個 Person 對象,它擁有一個屬性值__proto__,並且__proto__是一個對象,包含兩個屬性值 constructor 和__proto__

console.log(p.__proto__.constructor);   //function Person(){}
console.log(p.__proto__.__proto__);     //對象{},擁有很多屬性值

p.__proto__.constructor 返回的結果為構造函數本身,p.__proto__.__proto__有很多參數 

console.log(p.__proto__.__proto__)

我們調用 constructor 屬性,

p.__proto__.__proto __.constructor 得到擁有多個參數的Object()函數,

Person.prototype 的隱式原型的 constructor 指向Object(),即 Person.prototype.__proto__.constructor == Object()

從 p.__proto__.constructor 返回的結果為構造函數本身得到 Person.prototype.constructor == Person()

所以 p.__proto__.__proto__== Object.prototype

即 p.b 打印結果為b,p沒有b屬性,會一直通過__proto__向上查找,最后當查找到 Object.prototype 時找到,最后打印出b,

向上查找過程中,得到的是 Object.prototype,而不是 Function.prototype,找不到a屬性,

所以結果為 undefined,這就是原型鏈,通過__proto__向上進行查找,最終到null結束

console.log(p.__proto__.__proto__.__proto__);   //null
console.log(Object.prototype.__proto__);        //null

同理,得出以下結果

//Function
function Function(){}
console.log(Function);  //Function()
console.log(Function.prototype.constructor);    //Function()
console.log(Function.prototype.__proto__);      //Object.prototype
console.log(Function.prototype.__proto__.__proto__);    //NULL
console.log(Function.prototype.__proto__.constructor);  //Object()
console.log(Function.prototype.__proto__ === Object.prototype); //true

 

3、原型鏈的繼承

function Father(){
  this.name = 'Faker';
}

function Child(){
  this.age = 20;
}

Child.prototype = new Father();

var son = new Child();

 

四、總結

 

  • Object 是所有對象的爸爸,所有對象都可以通過 __proto__ 找到它
  • Function 是所有函數的爸爸,所有函數都可以通過 __proto__ 找到它
  • 函數的 prototype 是一個對象
  • 對象的 __proto__ 屬性指向原型, __proto__ 將對象和原型連接起來組成了原型鏈
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM