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

1、函數對象

 

  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

 

2、構造函數

//建立構造函數
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的隱式原型指向它構造函數的顯式原型,指向的意思是恆等於this

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

 

3、原型和原型鏈

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

因爲 p 是 Person() 的實例,是一個 Person 對象,它擁有一個屬性值__proto__,而且__proto__是一個對象,包含兩個屬性值 constructor 和__proto__spa

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

p.__proto__.constructor 返回的結果爲構造函數自己,p.__proto__.__proto__有不少參數 prototype

console.log(p.__proto__.__proto__)

咱們調用 constructor 屬性,code

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

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

從 p.__proto__.constructor 返回的結果爲構造函數自己獲得 Person.prototype.constructor == Person()blog

因此 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

 

4、總結

 

  1. 凡是經過 new function() 建立的對象都是函數對象,其餘的都是普通對象

  2. js 中全部的函數對象都有一個 prototype 屬性,這個屬性引用了一個對象,

    即原型對象,也簡稱原型。普通對象沒有 prototype,但有__proto__屬性

  3. js 在建立對象(不管是普通對象仍是函數對象)的時候,都有一個叫作

    __proto__的內置屬性,用於指向建立它的函數對象的原型對象 prototype(即它

    的構造函數的原型對象)

相關文章
相關標籤/搜索