重寫原型對象

引出問題函數

function Person(name, age) {}     // Person構造函數是個空函數,將默認值都放在原型對象中
    
    Person.prototype.name = 'xiaoming'
    Person.prototype.age = 20
    Person.prototype.sayHi = function() {
        console.log(`hi, ${this.name}`)
    }
    
    const p1 = new Person()
    
    /*
        實例對象的內部指針指向的是構造函數的原型對象
        構造函數的prototype屬性指向的也是這個原型對象
    
        實例對象和構造函數之間沒有直接的聯繫
    */
    
    console.log(p1.__proto__ === Person.prototype)    //true
  
    console.log(Person.prototype.constructor)
    
    /*
        ƒ Person(name, age) {
        this.name = name
        this.age = age
        this.sayHi = function() {
            console.log(`hi, ${this.name}`)
        }
        
        構造函數的原型對象中的constructor指向的是構造函數
    }
    */
    
    // 嘗試重寫Person構造函數的原型對象
    Person.prototype = {
        name: 'alice',
        age: 12,
        sayLove: function() {
            console.log(`i love ${this.name}`)
        }
    }
    
    console.log(Person.prototype.constructor)    // ƒ Object() { [native code] }

重寫了 prototype 以後發現它的constructor再也不指向 Person,而是指向了Object構造函數this

why ?prototype

明確一點,在調用構造函數的時候,會爲生成的新的實例對象添加一個指針指向構造函數的原型對象
那麼在重寫prototype的時候咱們用對象字面量的方式建立了一個新的對象,而用這種方式建立就至關於調用了Object構造函數
不信能夠試試指針

const o1 = {}
    const o2 = new Object()
    
    console.log(o1.__proto__ === o2.__proto__)    // true

此時,在調用了Object構造函數建立一個新對象,並將這個新對象做爲 Person 的 prototype 以後,
發現這個原型對象裏面少了一個constructor屬性;
當在一個實例對象中找不到該屬性時,就會去這個實例對象的構造函數的原型對象中尋找,
這個原型對象的構造函數是 Object,因此就會去 Object構造函數的原型對象中尋找,
而咱們前面說了,構造函數的原型對象中的constructor指向的是構造函數,
因此Object的原型對象中的constructor指向的仍是Object,code

那麼如何避免這種狀況呢?
若是constructor真的很重要,那麼在重寫原型對象的時候能夠在對象中加上constructor屬性,
這樣的話就不會去新對象的原型對象中查找constructor屬性了對象

Person.prototype = {
    constructor: Person,    // 注意這個值不是字符串
    name: 'alice',
    age: 12,
    sayLove: function() {
        console.log(`i love ${this.name}`)
    }
}

console.log(Person.prototype.constructor)
/*
    ƒ Person(name, age) {
    this.name = name
    this.age = age
    this.sayHi = function() {
        console.log(`hi, ${this.name}`)
    }
}
*/

仍然須要注意的是,在修改了構造函數的原型對象以後,即便給原型對象添加了constructor屬性,可是以前經過構造函數生成的實例對象不會自動更新它們的原型對象的指針。請看下方的例子:字符串

//咱們能夠看一下Person構造函數的原型對象
    
    console.log(Person.prototype)    //    {name: "alice", age: 12, sayLove: ƒ, constructor: ƒ}
    
    //再來看一下p1的原型對象指針指向的對象
    
    console.log(p1.__proto__)    //    {name: "xiaoming", age: 20, sayHi: ƒ, constructor: ƒ}

因此在修改了原型對象以後,只有在修改以後生成的實例對象上會有新的屬性和方法,以前的實例對象指向的仍然是以前的原型對象。原型

相關文章
相關標籤/搜索