重写原型对象

引出题目

    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组织函数

why ?

明白一点,在挪用组织函数的时刻,会为天生的新的实例对象增加一个指针指向组织函数的原型对象
那末在重写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,

那末怎样防止这类状况呢?
假如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: ƒ}

所以在修正了原型对象以后,只要在修正以后天生的实例对象上会有新的属性和要领,之前的实例对象指向的依然是之前的原型对象。

    原文作者:秦锋
    原文地址: https://segmentfault.com/a/1190000017235514
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞