0
点赞
收藏
分享

微信扫一扫

什么是面向对象,什么是原型链,原型链继承的运用,全网最详细讲解

奋斗De奶爸 2022-02-09 阅读 27
javascript

1.1-面向对象三大特征介绍

a.封装:将某个具体功能封装在对象中,只对外部暴露指定的接口,外界在使用的时候,只考虑接  口怎么用,不用考虑内部怎么实现(前面学习的api其实就是一种封装思想)

b.继承:一个对象拥有其他对象的属性和方法 ​

c.多态:一个对象在不同情况下的多种状态

<!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>Title</title>
 </head>
 <body>
 ​
 ​
 <script>
     /*面向对象三大特征
         a.封装:将某个具体功能封装在对象中,只对外部暴露指定的接口,外界在使用的时候,只考虑接口怎么用,不用考虑内部怎么实现
         b.继承:一个对象拥有其他对象的属性和方法
         c.多态:一个对象在不同情况下的多种状态
      */
 ​
 ​
     /*多态(了解即可,使用不多):一个对象在不同情况的多种状态
         饲养员对象Person : 给动物对象喂养食物  funtion work(animal,food){ animal.eat(food) }
         动物对象Animal : 吃东西  eat(food){ }
         多态 : 给不同的动物喂养食物,虽然都是调用eat()方法,但是不同的动物会执行不同的eat()
     */
     //示例:饲养员给动物喂食物
     
     //动物
     function Animal ( name ) {
         this.name = name;
     };
 ​
     //猫
     let cat = new Animal('猫咪');
     cat.eat = function ( food ) {
         console.log ( "喵喵猫" + "我吃了" + food );
     };
 ​
     //狗
     let dog = new Animal('小狗狗');
     dog.eat = function ( food ) {
         console.log ( "汪汪汪" + "我吃了" + food );
     };
 ​
     //饲养员
     function Person (  name ) {
         this.name = name;
     };
     Person.prototype.work = function (animal,food ) {
         //animal接收一个由Anmiaml构造函数生成的实例化对象,调用它的eat方法
         //同一对象表现出来不同的状态,就叫做多态
         animal.eat(food);
     };
 ​
     let p1 = new Person('ikun');
     p1.work(cat, '饼干');
     p1.work(dog, '翔');
 ​
 ​
 </script>
 </body>
 </html>

1.2-继承的三种实现方式

  • 继承:让一个对象拥有另一个对象的属性和方法

  • 知识点

    • 1.混入式继承 : 遍历 父对象 的所有属性值,添加给 子对象

      • 特点:每继承一次,就要执行一次循环

      • 应用场景:单个对象继承

    • 2.替换原型继承 : 将 父对象 作为 子对象构造函数的原型

      • 特点:会丢失原型之前的成员变量

      • 应用场景:多个对象继承

    • 3.混合式继承 : 混入式 + 替换原型

      • 特点 : 遍历 父对象 所有的属性值,添加给 子对象构造函数 的原型

1.混入式继承

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <title>Title</title>
 </head>
 <body>
 ​
 ​
 <script>
 ​
     /*学习目标 : 继承的三种实现方式 
         1.混入式继承 : 遍历 父对象 的所有属性值,添加给 子对象
             特点:每继承一次,就要执行一次循环
             应用场景:单个对象继承
 ​
         2.替换原型继承 : 将 父对象 作为 子对象构造函数的原型
             特点:会丢失原型之前的成员变量
             应用场景:多个对象继承
 ​
         3. 混合式继承 : 混入式 + 替换原型
             特点 : 遍历 父对象 所有的属性值,添加给 子对象构造函数 的原型
 ​
      */
     //继承:让一个对象拥有另一个对象的属性和方法
     let father = {
         house:{
             address:'北京一环',
             price:100000000
         },
         car:{
             brand:'劳斯莱斯',
             price:5000000
         }
     }
     let son = {
         name:'ikun',
         age:30
     }
     
 ​
     //1.混入式
     //解决方案:遍历父对象的所有属性值,添加给子对象
     //特点:每继承一次,就要执行一次循环
     //应用场景 : 单个对象继承
     
     for (let key in father){
         father[key] = son[key]
     }
     console.log ( son )
    
 ​
     
 ​
 ​
     
 </script>
 </body>
 </html>

2.替换原型继承

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>Document</title>
 </head>
 <body>
     <script>
     //2.替换原型
     //解决方案:将父对象作为子对象构造函数的原型
     //特点:会丢失原型之前的成员变量
     //应用场景:多个对象继承
     
     let father = {
         house:{
             address:'北京一环',
             price:100000000
         },
         car:{
             brand:'劳斯莱斯',
             price:5000000
         }
     }
 ​
     function Son (name,age  ) {
         this.name = name
         this.age = age
     }
 ​
     Son.prototype.sayHi = function(){
         console.log('你好')
     }
     
 ​
     //让父对象成为子对象构造函数的原型
     Son.prototype  = father
 ​
     //实例化对象
     let son1 = new Son('ikun',30)
     console.log ( son1 )
     let son2 = new Son('班长',20)
     console.log ( son2 )
     
     </script>
 </body>
 </html>

3.混合式继承

<!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>Document</title>
 </head>
 <body>
     <script>
     /*学习目标 : 继承的三种实现方式 
     1.混入式继承 : 遍历 父对象 的所有属性值,添加给 子对象
         特点:每继承一次,就要执行一次循环
         应用场景:单个对象继承
 ​
     2.替换原型继承 : 将 父对象 作为 子对象构造函数的原型
         特点:会丢失原型之前的成员变量
         应用场景:多个对象继承
 ​
     3. 混合式继承 : 混入式 + 替换原型
         特点 : 遍历 父对象 所有的属性值,添加给 子对象构造函数 的原型
 ​
      */
 ​
     //3.  混合式(混入+替换原型)
     //解决方案:遍历父对象所有的属性值,添加给子对象构造函数的原型
     let father = {
         house:{
             address:'北京一环',
             price:100000000
         },
         car:{
             brand:'劳斯莱斯',
             price:5000000
         }
     }
 ​
     function Son (name,age  ) {
         this.name = name
         this.age = age
     }
 ​
     Son.prototype.sayHi = function(){
         console.log('你好')
     }
 ​
    //将父对象的所有属性添加到子对象构造函数的原型中
     for(let key in father){
         Son.prototype[key] = father[key];
     }
 ​
     //实例化对象
     let son1 = new Son('ikun',30)
     console.log ( son1 )
     let son2 = new Son('班长',20)
     console.log ( son2 )
     </script>
 </body>
 </html>

02-原型链

==1.1-原型链介绍==

  • 知识点

    • 1.原型链:每一个对象都有原型,原型本身又是对象,所以原型又有原型,以此类推形成一个链式结构,称为原型链

    • 2.对象访问原型链中的成员规则:就近原则

      • 当访问一个对象的成员变量时,会首先访问它自身的成员变量,如果有则访问。没有则在原型中寻找,能找到就访问,不能找到则继续往原型的原型中寻找,以此类推,如果找到原型链的顶端还是找不到,则程序报错:xxx is not a function

 
<!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>Document</title>
 </head>
 <body>
     <script>
 ​
         /* 
         1.原型链 :每一个对象,都有__proto__指向自身的原型。 而原型也是对象,也有自己的
         __proto__指向原型的原型,以此类推形成链式结构,称之为原型链。
 ​
         2.对象访问原型链中成员的规则 :就近原则
             当访问对象的成员,先看自己有没有。有则访问,没有则看原型有没有。原型有则访问,
             没有则访问原型的原型,没有则继续往上找。以此类推,一直找到原型链终点 : null.
             还没有, 如果是属性 : 则获取undefined  如果是方法 ,则报错xxx is not defined 
          */
         
         //1.构造函数
         function Person(name,age){
             this.name = name;
             this.age = age;
         };
 ​
         //2.原型对象
         Person.prototype.sayHi = function(){
             console.log('人生若只如初见,何事秋风悲画扇');
         };
 ​
         Person.prototype.type = '哺乳动物';
 ​
         //3.实例化对象
         let p1 = new Person('又又',18);
         console.log(p1);
 ​
         //请说出以下代码执行结果
         console.log(p1.name);//又又      p1自己有name属性
         console.log(p1.type);//哺乳动物   p1自己没有type,但是p1的原型有
         console.log(p1.hobby);//undefined p1自己没有hobby,原型也没有
         p1.sayHi();// 人生若只如初见,何事秋风悲画扇   p1自己没有这个方法,原型有
        // p1.eat();//报错 xxx is not defined    p1自己没有这个方法,原型也没有
 ​
        //为什么不报错?  p1自己没有这个方法,原型也没有这个方法,但是原型的原型有
         p1.toString();
 ​
         //查看p1的原型链
         console.log(p1.__proto__.constructor);//Person
         console.log(p1.__proto__ === Person.prototype);//true
 ​
         //查看p1的原型的原型
         console.log(p1.__proto__.__proto__.constructor);//Object
         console.log(p1.__proto__.__proto__ === Object.prototype);//true
 ​
         //查看p1的原型的原型的原型
         console.log(p1.__proto__.__proto__.__proto__);//null
 ​
     </script>
 </body>
 </html>

1.2-原型链详解:内置对象的原型链

  • 知识点:内置对象的原型链

    • 1.查看Array的原型链

      • 构造函数的原型本身是一个对象,只要是对象就有原型

    • 2.查看Date的原型链

      • 所有的内置对象(Math Array 基本包装类型等)的原型链都是一样的,最终都指向Object

    • 3.查看String的原型链:了解这里的String值得是内置对象String(是一个基本包装类型),其他的Number、Boolean原型链和String是一样的

      • 只有对象才有原型,这里一定要把基本数据类型string、number、boolean,和基本包装类型(特殊的引用类型对象)String、Number、Boolean区分开来,不要搞混淆

1.Array的原型链

 //1.Array
     let arr = new Array(10,20,30);
     console.log ( arr );
     //查看arr的原型
     console.log ( arr.__proto__.constructor );//Array
     console.log ( arr.__proto__ === Array.prototype );
     //查看arr的原型的原型
     console.log ( arr.__proto__.__proto__.constructor );//Object
     console.log ( arr.__proto__.__proto__ === Object.prototype );//true

2-Date的原型链

//2.Date
     let date1 = new Date();
     //细节:日期对象直接console.log会转成string,查看对象需要使用console.dir打印
     console.dir(date1);
     console.log ( date1.__proto__ === Date.prototype );//true
     console.log ( date1.__proto__.__proto__.constructor );//Object
     console.log ( date1.__proto__.__proto__ === Object.prototype );//true

3-String对象原型链

//3.String
     let str = new String('123');
     console.log ( str );
     console.log ( str.__proto__ === String.prototype );//true
     console.log ( str.__proto__.__proto__.constructor );//Object
     console.log ( str.__proto__.__proto__ === Object.prototype );//true

4-DOM对象原型链

//4.界面元素
    let div1 = document.getElementById('div1');
    let p1 = document.getElementById('p1');

  • 完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="div1"></div>
<p id="p1"></p>

<script>
    /*查看内置对象的原型链*/

    //1.Array
    let arr = new Array(10,20,30);
    console.log ( arr );
    //查看arr的原型
    console.log ( arr.__proto__.constructor );//Array
    console.log ( arr.__proto__ === Array.prototype );
    //查看arr的原型的原型
    console.log ( arr.__proto__.__proto__.constructor );//Object
    console.log ( arr.__proto__.__proto__ === Object.prototype );//true

    //2.Date
    let date1 = new Date();
    //细节:日期对象直接console.log会转成string,查看对象需要使用console.dir打印
    console.dir(date1);
    console.log ( date1.__proto__ === Date.prototype );//true
    console.log ( date1.__proto__.__proto__.constructor );//Object
    console.log ( date1.__proto__.__proto__ === Object.prototype );//true

    //3.String
    let str = new String('123');
    console.log ( str );
    console.log ( str.__proto__ === String.prototype );//true
    console.log ( str.__proto__.__proto__.constructor );//Object
    console.log ( str.__proto__.__proto__ === Object.prototype );//true

    //4.界面元素
    let div1 = document.getElementById('div1');
    let p1 = document.getElementById('p1');

</script>
</body>
</html>
举报

相关推荐

0 条评论