一文大白话讲清楚 :类,实例,prototype,__proto__和原型链之间的关系

一文大白话讲清楚 :类,实例,prototype,__proto__和原型链之间的关系

1.类和实例的关系

  • 我问你,你是哪个国家的人,你会说我是中国人
  • 我又问你,你为什么说你是中国人,你说因为我有黄皮肤,黑眼睛,而且世世代代都是黄皮肤黑眼睛
  • 这两个问题包含了类和实例的两个核心问题:
  • 你和中国人之间,你是一个真真切切的可触摸的人,中国人确不是一个真真切切可触摸的人,但你又说你是中国人,那是为什么?
  • 那是因为中国人是一个抽象,可以理解为一个大的归类,而你是这个归类里面的具体的一个小类
  • 就好比植物和玉米的关系,植物是一种抽象,一种归类,而玉米是一个具象,是一个子类
  • 这就是类和实例的关系,类就是一个抽象,实例就是通过类具象化以后的一个具象,我们一般用new来完成具象操作
  • 上代码:
//我们定义一个类,中国人
class Chinese{
    constructor(){
        
    }
}
//然后我们根据中国人这个类,具象化一个具体的人,你,假设你叫张三
let zhangSan=new Chinese();
//Chinese是一个
//zhangSan是一个人,是一个被Chinese具象化的中国人

  • 上述代码说明了,张三是中国人,但张三说了,我是中国人是因为我有黄皮肤黑眼睛,说明所有的中国人都有黄皮肤和黑眼睛,也就是说中国人这个抽象,这个大类里面定义了一些人中国人独有的特点,每个具象化以后得中国人都继承了这个特点,这个特点就是类的属性
  • 我们在上述代码的基础上,给类加上属性
//我们定义一个类,中国人
class Chinese{
    constructor(yellowSkin,blackEyes){
        this.skin=yellowSkin;
        this.eyes=blackEyes;
    }
}
//然后我们根据中国人这个类,具象化一个具体的人,你,假设你叫张三
let zhangSan=new Chinese('yellowSkin','blackEyes');
console.log(zhangSan.skin,zhangSan.eyes)//yellowSkin  blackEyes
//打印出张三的皮肤是黄色皮肤,眼睛是黑色眼睛

2. prototype和__proto__

  • 在讲之前,我们接着上一个你和中国人的例子继续讲一下,我问你是哪里人,你会说你是中国人,我会说中国人这个范围太大了,再具体点是哪的,你说我是中国人,北京人

  • 也就是说,你,先是北京人,再往大然后是中国人

  • 即存在,你->北京人->中国人的关系

  • 那么我怎么知道这个逻辑关系呢

  • 这个就要靠继承

  • 啥意思,好理解,你可以用DNA检测法理解,大白话,你,你爹,你爷之间的关系,你爹为啥是你爹,因为你的DNA继承自你爹,为啥你爷是你爷,因为你爹的DNA继承自你爷

  • 明白了不,你继承了你爹的DNA,所以你们两就有血缘关系,你爹又继承了你爷的DNA,所以你爹和你爷就有血缘关系,所以你跟你爷也有血缘关系,这个DNA的传递就是继承,而这个血缘关系,就是原型链

  • 讲完这个故事,我们可以来讲prototype和__proto__了

  • prototype和__proto__都指向一个原型对象,也就是再往上一级,你是谁的问题

  • 不同的是,prototype是挂在类上的,__proto__是挂在实例上的,可以理解为引用的主体不同,如果查询类的原型对象,用类.prototype,查询对象的,用实例.proto

  • 上代码

class Person{
    constructor(){
        
    }
}
let obj=new Person()
console.log(obj.__proto__===Person.prototype)//true
  • 进一步理解就是,北京人这个大类里面,定义了一个prototype属性对象,里面定义了一个关于我们再往上一级是中国人的标记,如果你是由北京人这个类实例化来的人,那么你就也会有这个标记,只不过你在查这个标记的时候,不用在北京人这个类的prototype上查了,因为我在实例化你成为北京人的时候,给你添加了一个__proto__属性,这保存的就是类的prototype

  • 这下讲清楚prototype和__proto__了,再来说说原型链

3. 原型链

  • 第二节我们通过血缘关系已经说了原型链,就说凡是挂在北京人这个类的prototype上的属性和方法,我们被实例化的北京人都可以调用
  • 上代码
class BeijingPerson{
    constructor(homePalce) {
       
        this.homePlace=homePalce
    }

}
BeijingPerson.prototype.sayHomePlace=function (){
    console.log(`My home place id ${this.homePlace}`)
}
let bjPerson=new BeijingPerson('Beijing')
bjPerson.sayHomePlace()//My home place id Beijing

  • 而血缘关系就是,如果我继承了你,那么我的DNA就是你的DNA
  • 对于类和实例,如果北京人这个类,继承了中国人这个类,那么北京人这个类的prototype就是中国人这个类的一个实例对象,而且每个由北京人这个类实例化的北京人对象的__proto__也包含中国人这个类的一个实例对象
  • 我们用北京人继承自中国人,中国人继承自地球人这个逻辑关系来演示一下
//地球人
class Earth{
    constructor(circle){
        this.circle=circle
    }
}

//中国人继承自地球人
class Chinese extends Earth{
    constructor(skin,circle){
        super(circle)
        this.skin=skin
    }
}

//北京人继承自中国人
class BeijingPerson extends Chinese{
    constructor(homePlace,skin,circle) {
        super(skin,circle)
        this.homePlae=homePlace

    }

}
//用北京人这个类实例化一个北京人
let bjPerson=new BeijingPerson('beijing','yellow','circle')

console.log(bjPerson.__proto__)//Chinese {}
//实例化后的北京人这个对象的__proto__指向北京人这个类继承的类实例化的一个对象
console.log(bjPerson.__proto__.__proto__)//Earth {}
//再往上寻找一级,实例化后的北京人这个对象的__proto__的__proto__指向北京人这个类继承的类继承的类实例化的一个对象
console.log(bjPerson.__proto__.__proto__.__proto__)//{}
//依此类推
console.log(bjPerson.__proto__===BeijingPerson.prototype)

4. prototype和constructor的关系

  • 首先,每个类都有prototype和constructor,constructor每个类都有还好理解,prototype怎么说,如果定义了一个类,压根没继承任何东西,会有prototype么?答案是肯定的,会,因为我们定义的任何一个类都默认继承了Obejct类,所以默认的prototype都指向{}
  • 那么prototype和constructor时间有什么联系呢
  • 每个prototype里面都有一个constructor,而这个constructor指向类自己
  • 啥意思,上代码
class Earth{
    constructor(circle){
        this.circle=circle
    }
}
//我们用Earth的构造函数实例化一个对象
let obj=new Earth('circle');
console.log(obj)//Earth { circle: 'cirecle' }

//我们又说,Earth的prototype里面有一个constructor,而且指向类本身,那么就意味着
//Earth===Earth.prototype.constructor
//所以我们还可以这么实例化一个Earth,是不是点意思

let obj1=new Earth.prototype.constructor('cirecle')
console.log(obj1)//Earth { circle: 'cirecle' }
console.log(Earth===Earth.prototype.constructor)//true
  • 这就开始循环了,类的prototype里面有constructor,而constructor又指向类
  • 而类又有prototype
  • 这就是为啥大家在浏览器里面打印__proto__时,发现一层包着一层,无限打开了
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

许先森森

爱我就打我

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值