资讯专栏INFORMATION COLUMN

重写原型对象

陈江龙 / 1065人阅读

摘要:请看下方的例子我们可以看一下构造函数的原型对象再来看一下的原型对象指针指向的对象所以在修改了原型对象之后,只有在修改之后生成的实例对象上会有新的属性和方法,之前的实例对象指向的仍然是之前的原型对象。

引出问题

    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://www.ucloud.cn/yun/99665.html

相关文章

  • JavaScript,从示例理解重写原型后的指针指向

    摘要:我们知道,调用构造函数时会为实例添加一个指向最初原型的指针,而把原型修改为另外一个对象就等于切断了构造函数与最初原型之间的联系。 我们知道,调用构造函数时会为实例添加一个指向最初原型的指针,而把原型修改为另外一个对象就等于切断了构造函数与最初原型之间的联系。 怎么理解这句话,下面我们通过实例来解释下,如有不对,请指正,虚心受教。 function Person(){ } ...

    godlong_X 评论0 收藏0
  • [js高手之路]使用原型对象(prototype)需要注意的地方

    摘要:原型对象的共享特性,可以很方便的为一些内置的对象扩展一些方法,比如,数组去重复但是,不要随便往内置的对象上面扩展方法,在多人协作开发,很容易产生覆盖,以及污染 我们先来一个简单的构造函数+原型对象的小程序 1 function CreateObj( uName, uAge ) { 2 this.userName = uName; 3 ...

    chnmagnus 评论0 收藏0
  • 我来重新学习 javascript 的面向对象(part 2)

    摘要:先来说其实构造函数也有,原型对象有,实例有也有,或者更加笼统的说,所有对象都是有的。构造函数的原型对象上的会指向构造函数。由于属性是可以变更的,所以未必真的指向对象的构造函数,只是一个提示。 续上一集内容,通过构造函数的方式,成功地更新了生产技术,老板笑呵呵,工人少奔波,只是问题总比办法多,又遇到一个新问题,就是会造成一些资源的重复和浪费,那么经过工程师们的智慧交流,他们产生了一个新技...

    silvertheo 评论0 收藏0
  • js对象创建方法汇总及对比

    摘要:中创建对象的方式有很多,尤其是基于原型的方式创建对象,是理解基于原型继承的基础。该函数中的属性指向该源性对象当通过该函数的构造函数创建一个具体对象时,在这个对象中,就会有一个属性指向原型。 js中创建对象的方式有很多,尤其是基于原型的方式创建对象,是理解基于原型继承的基础。因此在这里汇总一下,并对各种方法的利弊进行总结和对比,不至于以后对这些概念有模糊。 简单方式创建 var o = ...

    piapia 评论0 收藏0
  • 创建对象(一):创建与继承

    摘要:创建实例的方式有三种对象字面量表示法操作符跟构造函数中的函数。下面主要讲的是最为复杂的操作符跟构造函数的创建对象实例的方法。 创建对象 一.创建对象的方法 理解原型对象: 无论什么时候,只要创建了新函数,就会根据一组特定的规则为该函数创建一个 prototype属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个constructor属性,这个属性包含一个指向p...

    microelec 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<