js 原型鏈詳解

在下月亮有何貴幹發表於2021-10-29

建構函式和例項

假設你宣告一個方法叫做Foo(),那麼我們可以通過new Foo()來宣告例項。

    function Foo() {
      console.log("我是一個構造方法");
    }
    const f1 = new Foo();

現在你可以很清晰的明白Foo()是建構函式,f1是它的例項

屬性Prototype

Foo()這個建構函式是一個方法。

方法也是物件資料型別,所以可以說方法是個物件。

物件就有屬性,不過方法有自己特殊的一個屬性,叫做prototype,其他物件沒有哦。

這個屬性會指向一個原型物件(Foo.prototype),而原型物件也會有一個自己的屬性叫做constructor,指向屬性包含了一個指標,指回原建構函式。

    function Foo() {
      console.log("我是一個構造方法");
    }
    const f1 = new Foo();

    console.log(Foo.prototype);//Foo的原型物件
    console.log(f1.prototype);//f1沒有 underfied

在這裡插入圖片描述

屬性__proto__

上文的prototype是給建構函式的所有例項提供共享方法和屬性的。

例項又是怎麼訪問到共享方法和屬性的呢?

f1例項沒有prototype,而有一個屬性__proto__,這是所有物件都有的屬性,它指向到構造自己的建構函式原型物件,然後js這個語言就是根據這個屬性來讓例項訪問到共享屬性和方法的

Foo是f1的建構函式,Foo.prototype是Foo的原型物件,所以f1.__proto__指向Foo.prototype

    function Foo() {
      console.log("我是一個構造方法");
    }

    const f1 = new Foo();

    console.log(Foo.prototype);
    console.log(f1.__proto__);

在這裡插入圖片描述

訪問原型上的方法

Foo這個建構函式如果希望自己的例項能夠擁有同一個屬性,比如name,就在自己的原型物件上加上。

    function Foo() {
      console.log("我是一個方法");
    }

    Foo.prototype.name = "我是Foo創造的例項共享的屬性";

    const f1 = new Foo();
    const f2 = new Foo();

    console.log(f1.name);//我是Foo創造的例項共享的屬性
    console.log(f2.name);//我是Foo創造的例項共享的屬性

在這裡插入圖片描述

建構函式也有__proto__

上面說所有物件都有__proto__,Foo是函式也是物件啊,所以Foo.__proto__是啥呢?

那就去找Foo的建構函式是誰呢,Foo是一個函式,擁有函式特有的方法和屬性,創造的它的建構函式就是Function,這個js自帶的的一個建構函式,它的Function.prototype給所有js中你建立的函式提供函式自帶的一些公共方法和屬性。

所以Foo.__proto__指向Funtion.prototype

建構函式的原型也有__proto__

Foo.prototype也是物件,所以它也有__proto__。

每當我們要找__proto__,就得找它的建構函式,Foo.prototype是個物件,純物件,所以它的建構函式是Object,那麼Object的原型就是Object.prototype。

Foo.prototype.__proto__指向Object.prototype

Object.prototype這個原型物件很特殊

Array、String、Funtion、Object這些建構函式都是函式
都是Funtion建構函式的例項,
Array.__proto__、String.__proto__、Funtion.__proto__、Object.__proto__指向Funtion.prototype原型,
可以呼叫Funtion.prototype原型的一些公共方法,
例如都可以呼叫.name檢視自己的函式名字。

Array.prototype、String.prototype、Funtion.prototype這些原型物件都是物件
都是Object建構函式的例項,
Array.prototype.__proto__、String.prototype.__proto__、Funtion.prototype.__proto__指向Object.prototype原型,
所以可以呼叫Object.prototype這個原型物件的公共方法,

Object.prototype有些特殊,它雖然是物件,但是並不是Object自己的例項,
Object.prototype.__proto__指向null,作為原型鏈的終點

總結

  1. 方法,也就是函式,才有prototype,就是方法的原型。
  2. 所以例項,一般都會有個對應的構造方法,也就是建構函式,例項的__proto__指向構造方法的原型。
  3. js有很多自帶的構造方法,例如Array、String、Funtion、Object,都是根據js一些物件型別分配的,他們的原型上提供了許多封裝好的常用方法。
  4. 所有構造方法本身是函式,是Funtion這個js自帶建構函式的例項
  5. 除了Object.prototype,所有構造方法的原型本身是物件,是Object這個js自帶建構函式的例項
  6. Object.prototype.__prototype指向null,作為原型鏈重點

在這裡插入圖片描述

相關文章