重写原型对象

引出问题函数

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: ƒ}

因此在修改了原型对象以后,只有在修改以后生成的实例对象上会有新的属性和方法,以前的实例对象指向的仍然是以前的原型对象。原型

相关文章
相关标签/搜索