天天看點

JavaScript中的原型和原型鍊

先上張圖

構造函數

上面的圖看懂了麼,沒懂不要緊。先看個栗子:

function Foo() { }
Foo.prototype.name = 'haha'
const foo = new Foo()
const bar = new Foo()
console.log(foo.name) // haha
console.log(bar.name) // haha
複制代碼
           

沒錯,這個

Foo

是構造函數,

foo

是執行個體對象。嗯,繼續往下看。

原型

  • prototype(原型對象)

    prototype

    :是一個對象,這個對象包含了所有執行個體對象共享的屬性和方法。每個函數都有

    prototype

    屬性(除了bind、箭頭函數、Function.prototype),但也隻有函數才擁有這個屬性。

    我們把

    Foo.prototype

    列印出來,可以看出它包含了執行個體對象

    foo 和 bar

    共同的屬性

    name = 'haha'

    constructor

    __proto__

    當作沒看到。哈哈,開玩笑,既然看到了,就分析下這兩妖孽是啥。
  • __proto__(原型指針)

    __proto__

    :每個

    js

    對象都有這個屬性(除了

    null

    ),顧名思義,它指向的是該執行個體對象的原型對象。比如說,栗子中執行個體對象

    foo

    __proto__

    就是

    Foo.prototype

    console.log(foo.__proto__ === Foo.prototype) // true
    複制代碼
               
  • constructor

    constructor

    :每個

    prototype

    原型都有個

    constructor

    ,它指向的是構造函數。上面栗子中

    Foo.prototype

    constructor

    就是構造函數

    Foo

    console.log(Foo.prototype.constructor === Foo) // true
    複制代碼
               

原型鍊

以上,我們可以看出構造函數、原型對象、執行個體之間的關系。每個構造函數都有一個原型對象(

prototype

),原型對象都包含一個指向構造函數的指針(

constructor

),而每個執行個體都包含一個指向原型對象的指針(

__proto__

)。

如果原型對象(

prototype

)是個執行個體呢,這樣我們通過

Foo.prototype.__proto__

又會找到另一個原型對象(

Object.prototype

)。如此層層遞進,執行個體與原型就形成了一個鍊條,這就是原型鍊。

console.log(Foo.prototype.__proto__ === Object.prototype) // true
複制代碼
           

來自于生命起源的問題,先有雞還是先有蛋

console.log(Function.__proto__ === Function.prototype) // true
console.log(Function.__proto__.__proto__ === Object.prototype) // true
console.log(Object.__proto__ === Function.prototype) // true
複制代碼
           

有興趣的可以看看知乎上的讨論

繼續閱讀