首頁 >web前端 >js教程 >圖解prototype、proto和constructor的三角關係

圖解prototype、proto和constructor的三角關係

亚连
亚连原創
2018-05-19 16:22:351612瀏覽

在javascript中,prototype、constructor以及__proto__之間有著「著名」的剪不斷理還亂的三角關係,以下由我帶領大家詳細講解這些關係。

  javascript裡的關係又多又亂。作用域鍊是一種單向的鍊式關係,還算簡單清晰;this機制的呼叫關係,稍微有些複雜;而關於原型,則是prototype、proto和constructor的三角關係。本文先用一張圖開宗明義,然後詳細解釋原型的三角關係

圖示

#概念

##  上圖中的複雜關係,實際上來源就兩行程式碼

function Foo(){};var f1 = new Foo;

【建構子】

  用來初始化新建立的物件的函數是建構子。在範例中,Foo()函數是建構子

【實例物件】

  透過建構函式的new操作所建立的物件是實例物件。可以用一個建構函數,建構多個實例物件

function Foo(){};
var f1 = new Foo;
var f2 = new Foo;
console.log(f1 === f2);//false

【原型物件及prototype】

  建構子有一個prototype屬性,指向實例物件的原型物件。透過同一個建構函數實例化的多個物件具有相同的原型物件。常使用原型物件來實作繼承

function Foo(){};
Foo.prototype.a = 1;
var f1 = new Foo;
var f2 = new Foo;console.log(Foo.prototype.a);
//1
console.log(f1.a);//1
console.log(f2.a);//1

【constructor】

  原型物件有一個constructor屬性,指向該原型物件對應的建構子

function Foo(){};
console.log(Foo.prototype.constructor === Foo);//true

  由於實例物件可以繼承原型物件的屬性,所以實例物件也擁有constructor屬性,同樣指向原型物件對應的建構子

function Foo(){};
var f1 = new Foo;
console.log(f1.constructor === Foo);//true

【proto】

  實例物件有一個proto屬性,指向該實例物件對應的原型物件

function Foo(){};
var f1 = new Foo;
console.log(f1.__proto__ === Foo.prototype);//true

說明

  概念介紹完了,現在對圖示的關係進行詳細說明

function Foo(){};
var f1 = new Foo;

【第一部分:Foo】

  

實例物件f1是透過建構子Foo()的new操作建立的。建構子Foo()的原型物件是Foo.prototype;實例物件f1透過__proto__屬性也指向原型物件Foo.prototype

function Foo(){};
var f1 = new Foo;
console.log(f1.__proto === Foo.prototype);//true

  實例物件f1本身並沒有constructor屬性,但它可以繼承原型物件Foo.prototype的constructor屬性

function Foo(){};
var f1 = new Foo;console.log(Foo.prototype.constructor === Foo);//true
console.log(f1.constructor === Foo);//true
console.log(f1.hasOwnProperty('constructor'));//false

  下圖是實例物件f1的控制台效果

【第二部分: Object】

  

Foo.prototype是f1的原型對象,同時它也是實例對象。實際上,任何物件都可以看做是透過Object()建構子的new操作實例化的對象  所以,Foo.prototype作為實例對象,它的建構子是Object(),原型對像是Object.prototype。對應地,建構子Object()的prototype屬性指向原型物件Object;實例物件Foo.prototype的proto屬性同樣指向原型物件Object

function Foo(){};
var f1 = new Foo;
console.log(Foo.prototype.__proto__ === Object.prototype);//true

  實例物件Foo.prototype本身俱有constructor屬性,所以它會覆寫繼承自原型物件Object.prototype的constructor屬性

function Foo(){};
var f1 = new Foo;
console.log(Foo.prototype.constructor === Foo);//true
console.log(Object.prototype.constructor === Object);//true
console.log(Foo.prototype.hasOwnProperty('constructor'));//true

  下圖是實例物件Foo.prototype的控制台效果

  如果Object.prototype作為實例物件的話,其原型物件是什麼,結果是null。私以為,這可能也是typeof null的結果是'object'的原因之一吧

console.log(Object.prototype.__proto__ === null);//true

#【第三部分: Function】

##  前面已經介紹過,函數也是對象,只不過是有特殊功能的對象而已。任何函數都可以看做是透過Function()建構子的new操作實例化的結果

  如果把函數Foo當成實例物件的話,其建構子是Function(),其原型物件是Function.prototype ;類似地,函式Object的建構子也是Function(),其原型物件是Function.prototype

function Foo(){};
var f1 = new Foo;console.log(Foo.__proto__ === Function.prototype);//true
console.log(Object.__proto__ === Function.prototype);//true

  原型物件Function.prototype的constructor屬性指向建構函式Function();實例物件Object和Foo本身沒有constructor屬性,需要繼承原型物件Function.prototype的constructor屬性

function Foo(){};
var f1 = new Foo;
console.log(Function.prototype.constructor === Function);//true
console.log(Foo.constructor === Function);//true
console.log(Foo.hasOwnProperty('constructor'));//false
console.log(Object.constructor === Function);//true
console.log(Object.hasOwnProperty('constructor'));//false

  所有的函數都可以看成是建構子Function()的new操作的實例化物件。那麼,Function可以看成是呼叫其自身的new操作的實例化的結果

  所以,如果Function作為實例對象,其構造函數是Function,其原型對像是Function.prototype

console.log(Function.__proto__ === Function.prototype);//true
console.log(Function.prototype.constructor === Function);//true
console.log(Function.prototype === Function);//true

  如果Function.prototype作為實例物件的話,其原型物件是什麼呢?和前面一樣,所有的物件都可以看成是Object()建構子的new操作的實例化結果。所以,Function.prototype的原型物件是Object.prototype,其原型函數是Object()

console.log(Function.prototype.__proto__ === Object.prototype);//true

  第二部分介紹過,Object.prototype的原型物件是null

console.log(Object.prototype.__proto__ === null);//true

总结

  【1】函数(Function也是函数)是new Function的结果,所以函数可以作为实例对象,其构造函数是Function(),原型对象是Function.prototype

  【2】对象(函数也是对象)是new Object的结果,所以对象可以作为实例对象,其构造函数是Object(),原型对象是Object.prototype

  【3】Object.prototype的原型对象是null

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

js querySelector() 基本使用方法(图文教程)

Es6 写的文件import解决方案(详细解读)

JavaScript 输出显示内容(基础的教程)

以上是圖解prototype、proto和constructor的三角關係的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn