原型链,原型对象。

一.原型对象是什么?

任何一个js对象它都有有一个原型对象,这个原型对象是js内置的,原型对象有那些属性和方法,下面的对象可以使用它原型上的一些属性和方法。

js对象指的是:引用类型的对象,列如,数组,对象,函数等

(1)数组的原型对象

 let arr=[10,20,30,40,50]
   console.log(arr);

(2)对象

  <script>
  // 一个数组
     let obj={
       name:'Lisa',
       age:20
     }
     console.log(obj);
  </script>
  

 (3)挂载原型对象方法的两种方法

   1.通过__proto__属性

 let arr=[10,20,30,40,50,]
  arr.__proto__.q=function(){
   console.log(`起风了`);
  }
  console.log(arr);

图示:

访问后:

 arr.qifeng()

2.通过构造函数的prototype属性进行挂载 

1.图示

    c.eat()-------------------------吃饭,依然能够访问

(4)结论

综上所述,可以得出一个结论,每一个js对象都有它的原型对象,这个原型对象是干嘛的呢,放了一些属性和方法,怎么在原型对象里面放入属性和方法,例如通过_proto_属性,如果是一个构造函数的话,那么可以通过prototype属性添加,原型对象是js内置的东西。

二.原型链

1.概念

定义:每一个构造函数都有原型对象,可以通过实例化对象的__proto__属性去访问构造函数原型对象上的属性和方法,那么它的原型对象上也是一个对象,凡是对象都有原型对象,如果构造函数的原型对象上没有,就会一层一层的网上找,最后的一个找到的是Object.prototype上,否则就会报错。

2.验证

每一个构造函数都有原型对象,可以通过实例化对象的__proto__属性去访问构造函数原型对象上的属性和方法。

(1):代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    function Start(name,age){
      this.name=name
      this.age=age
    }
    Start.prototype.eat=function(){
      console.log(`蛋炒饭`);
    }
    // 我是一个实例化对象
    var Person=new Start('王五',20)
    
  </script>
</body>
</html>

解析:由上面可见的是声明了一个构造函数,打印了它的实例化对象

图示:

访问的第一种方法:  Person.eat()

访问的第二种方法:  Person.__proto__.eat()

验证: console.log(Person.eat()===Person.__proto__.eat()); //true

得出结论:实例化对象的__proto__指向它的原型对象

3.讲了这么多的原型对象那有什么作用呢?

答:扩展对象

(1)现在简单的用原型对象来扩展一个对象

(2)代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    // 这是一个时间对象
    let dat=new Date()
    Date.prototype.formate=function(){
      let year=this.getFullYear()
      let month=this.getMonth()+1
      let date=this.getDate();
      return `${year}年${month}月${date}日`
    }
    console.log(dat.formate());
    
  </script>
  
</body>
</html>

(3)图示:

4.验证

那么它的原型对象上也是一个对象,凡是对象都有原型对象,如果构造函数的原型对象上没有,就会一层一层的网上找,最后的一个找到的是Object.prototype上,否则就会报错。

(1)在这之前要先提出一个概念

class类,是es6新增加的一种,定义构造函数的方法,通过extends关键字可以继承父类的属性和方法。

(2)代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    // 这是一个学生的类
    class  Stundent{
      constructor(name,age){
        this.name=name
        this.age=age
      }
      login(){
        console.log(`登录`);
      }
    }
    // 这个一个老师的类
    class Teacher extends  Stundent{
      tuichu(){
        console.log('退出');
      }
    }
    
    let teacher=new Teacher()
    console.log(teacher);

  

  </script>
  
</body>
</html>

图示(1-1)

(3)访问父类的属性和方法

 teacher.login() //登录
 teacher.tuichu() //退出

图示(1-2)

(4)根据图示(1-1)可以推测一下访问的规则。

据图(1-1)可以看到两个原型对象,一个是退tuichu这个函数是挂载到teacher的原型对象上的方法,根据图示(1-2)可以访问到上面的退出方法。代码: // teacher.tuichu(),那么通过实例化的__proto__属性也是可以访问到的,代码:teacher.__proto__.tuichu() .从图中可以看出它的原型对象上也是有login()这个方法的那么通过,它的原型对象上的__proto__属性也是可以拿到,登录的方法。

     teacher.__proto__.login()

图示:

(5)这种查找的链式关系被叫做是原型链

二.原型链的查找机制

如果在当前对象里面找不到方法,就会去隐式原型去找,如果发现__proto__隐式原型上有该方法也会访问该方法,如果没有会继续向下一个隐式原型__proto__去进行查找,知道找不到为止。

三.实现es5构造函数的一个继承。

前言:因为es5没有类的这个概念,如果要实现继承需要一些辅助的方法。

代码:

function Person(name,age){
      this.name=name
      this.age=age
    }
    Person.prototype.eat=function(){
      console.log(`蛋炒饭`);
    }
 
   function Person1(name,age){
      this.name=name
      this.age=age
   }

解析:可以看出下面的构造函数person1是没有eat方法的,打印他们两个的实例化对象可以得到

 在es6中可以使用extends关键字来实现继承,那么在es5中是如何实现的呢?

那我们可以将new Person()上的eat给 Person.prototype上。

代码:

  Person1.prototype=new Person()
   
  new Person1().eat()

图示:

四.通过instanceof来判断数据的类型也用到了原型链

(1)在我们用instanceof判断数组的时候

 <script>
    let arr=[]

    console.log(arr instanceof Array); //true

    console.log(arr instanceof Object); //true

  </script>

可以看出instanceof不能准确的判断数组类型

那为什么我们在判断数组和对象的时候都是,true呢?

根据我们打印的来看,

接着找:

 这就说明了以前说的一点,万物皆对象。

(2)当在判断对象的时候

代码:

<script>
    let obj={
      name:'王五'
    }
    console.log(obj instanceof Object); //true
    
    console.log(obj instanceof  Array); //false
  </script>

图示:

五.关于Constructor的指向问题

1.写一个构造函数

<script>
    function fn(name,age){
      this.name=name
      this.age=age
    }
    let a=new fn()
    
    console.log(a);
  </script>
  

图示:

   console.log(a instanceof fn); //true

2.如果按照es6的写法写一个类呢?

代码:

  <script>
    class Student{
      constructor(name,age){
        this.name=name
        this.age=age
      }
    }

    let a1=new Student('王五',20)
    console.log(a1);
  </script>

图示:

 console.log(a1 instanceof Student);返回的结果任然是一个true。总上所述,Constructor是一个指回过程,指向原来的构造函数。

六.通过学习大家对原型链应该有很深的了解。

(1)代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    class Student{
      constructor(name,age){
        this.name=name
        this.age=age
      }

      login(){
        console.log(`登录`);
      }
    }
    class Teacher extends Student{
      tuichu(){
        console.log(`退出`);
      }
    }
    let a1=new Teacher('WANWAN',20)

     
  //  console.log(a1.__proto__.__proto__.login());
  //  console.log(a1.login());

  
</body>
</html>

总结:
  // 通过第一层的a1.__proto__能偶访问Teacher的显示原型
  // 在通过__proto__就能访问到Student的显示原型
  // 但是我们一般都不去直接一个个地区写,它会自己去查找

(2)图示

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值