__proto__、Prototype、constructor


__proto__

__proto__属性指向原型对象,也可以理解为父类对象,它是所有对象(包括函数)都有的。

prototype

函数的原型对象,给其它对象提供共享属性,函数所独有的。它跟原型链没有关系。它的作用是:构造函数new对象的时候,告诉构造函数新创建的对象的原型是谁。

原型链

当你在访问一个对象属性的时候,如果该对象内部不存在这个属性,那么就回去它的__proto__属性所指向的对象(父类对象)上查找,如果父类对象依旧不存在这个属性,那么就回去其父类的__proto__属性所指向的父类的父类上去查找。以此类推,直到找到 null。而这个查找的过程,也就构成了我们常说的原型链。

constructor

constructor属性是一个对象指向该对象的构造函数。对象所独有属性。每一个对象都有其对应的构造函数,本身或者继承而来。

通常obj.constructor === obj.__proto__.constructor

原型继承

让子类的原型对象指向父类的实例,当子类的实例找不到对应的属性时,他会沿着原型链往上找。

__proto__ 与 prototype 与 constructor

function Father(){ this.a =1; }   // Father是函数对象

let child = new Father()          // child是普通对象        
  • Father._ proto_ === Function.prototype    // 函数对象的原型指向函数的原型对象
  • Function._ proto_ === Function.prototype     // Function的原型指向函数原型对象
  • Object._ proto_ === Function.prototype        //Object的原型指向函数原型对象
  • Function.prototype._ proto_ === Object.prototype       //Function的原型对象的原型指向Object的原型对象

上述四个看着很蒙?那么看下面三个

  • child._ proto_ === Father.prototype                     //child 的原型指向构造函数Father的原型对象
  • Father.prototype._ proto_ === Object.prototype  //Father 的原型对象的原型指向Object的原型对象
  • Object.prototype._ proto_ === null                      //Object的原型对象的原型指向null【原型链顶层】

child是通过Father使用new构造出来的实例对象,所以child的原型指向Father的prototype

其实child.constructor是在__proto__原型中找到的constructor

child.constructor === Father    // true
child.__proto__.constructor === child.constructor     // true

所以其实是这么一个结构:

子类实例对象:(

  属性方法

  __proto__ ==> 父类(

    父类属性方法

    constructor: function 子类(){}

    __proto__ ==> 父类的父类(

      父类的父类属性方法

      constructor: function 父类(){}

      __proto__。。。一直套娃,最后套到Object,然后是null

    )

  )

)

下面看一段原型代码

function Foo(name) {
  this.name = name;
}
Foo.prototype.myName = function(){
  return this.name;
}
function Bar(name, label){
  Foo.call(this,name);
  this.label = label;
}
// 创建新的Bar.prototype对象并关联到Foo.prototype
Bar.prototype = Object.create(Foo.prototype);
// Notice!现在没有Foo.prototype.constructor了,因为prototype被整个替换成了{}
Bar.prototype.myLabel = function(){ return this.label; } var a = new Bar('a', 'obj a'); a.myName(); //'a' a.myLabel(); //'obj a'

解决办法

可以使用ES6提供的新方法,这样就不会破坏结构了

Object.setPrototypeOf(Bar.prototype, Foo.prototype)

 引用:https://blog.csdn.net/m0_38073011/article/details/108500396

js