• 3.面向对象的三大特征中的 “继承” 和继承的几种方式



    学习继承之前,要先了解什么是面向对象:(把相同的代码提取(抽象)出来归为一类,把公共的方法挂在 这个类的原型上 的一种编程思想(开发模式))
    >>原型和原型链,在,面向对象,的那个随笔分类里有细说。<<
    面向对象的三大特征:抽象、封装、继承、(多态)

    抽象:提取类似的部分。

    封装:归类的过程。
    继承:子类拥有父类的属性或者方法,自己也有自己的一套属性和方法。

    /******************************** 下面开始这篇随笔的主题:继承 和 继承的几种方式********************************/

    网上对继承的方式,描述都不一样,主要是起的名字不一样,但这不重要,从代码的原理上大致可以分成4种,我给他们起来我心中的名字
    注意:
    1. call继承(属性继承/类式继承)
        一般我们把属性放在类里面,方法挂在原型上。
        调用父类,通过call来改变this(把window改成子类)

    达到继承属性的目的。
    例子:
        function Person(name,age){
            this.name = name;
            this.age = age;
        }
        function Coder(name,age,job){
            Person.call(this,name,age);
            this.job = job;
            // console.log(this);//Coder
        }
        let p = new Person('成龙',58);
        let c = new Coder('房祖名',26,'演员');
    
        console.log(c);//Coder {name: "房祖名", age: 26, job: "演员"}
        console.log(p);//Person {name: "成龙", age: 58}

    2.拷贝继承

    原理:1.用  for  in 循环 Person.prototype,再复制给 Coder.prototype,这样Coder的实例 c 就可以使用 Person.prototype上的方法。

       2.再结合 call 继承属性,,此时就完成了 属性和方法 的继承。

    注意:for in  会遍历整个原型链,(除了Person的原型,还会找Person的构造函数的原型。)为了保证只继承Person的方法,不包括 “祖先们” 的方法,此时需要用到

       hasOwnproperty() 这个方法类判断一下

    缺点:会遍历整个原型链,性能消耗大

    例子:

    for(let attr in Person.prototype){
            //必须保证赋值的数据是父级自身的属性
            if(Person.prototype.hasOwnProperty(attr)){
                Coder.prototype[attr] = Person.prototype[attr];
            }
        }

    3.原型继承  (有人叫寄生组合式继承) 推荐指数❤❤❤❤❤

    原理:1.继承属性:用 call 继承的方法

       2.继承方法:炮灰.prototype = Person.prototype

             Coder.prototype = new 炮灰

       3.手动赋值一个 constructor 指向子类:

             Coder.prototype.constructor = Coder

    很多可以继承的方法的核心原理就是这里提到的原型继承。比如 Object.create() / Object.assign() / Object.defineProperties() 。例子1过后,再简单介绍这些方法。

    例子1:
     1 function Person(name,age){
     2         this.name = name;
     3         this.age = age;
     4     }
     5 
     6 Person.prototype.say = function(){
     7         console.log(this.name+':呵呵');
     8     };
     9   
    10 function Coder(name,age){
    11         Person.call(this,name,age);
    12     }//子类私有继承父类私有
    13  
    14 Coder.prototype = Object.create(Person.prototype);
    15 Coder.prototype.constructor = Coder;//子类公有继承父类共有
    16  
    17 let p = new Person('成龙',68);
    18 let c = new Coder('房祖名',29);
    19 
    20 /*    子类改变属性,不会影响父级
    21 c.name = 1
    22 console.log(c.name);//1
    23 console.log(p.name);//成龙  */
    24 
    25 c.say();//成龙:呵呵
    26 p.say()//房祖名:呵呵

    例子2:Object.create():

    Coder.prototype = Object.create(Person.prototype)//此时就完成了属性继承,注意:手动修改 constructor 的指向。
    Object.create:内置Object类天生自带的方法
    1.创建一个空对象
    2.让新创建的空对象的__proto__指向第一个传递进来的对象

        Object.assign():浅拷贝

    Coder.prototype = Object.assign({},Person.prototype); //类似拷贝
    Object.assign(Coder.prototype,Person.prototype)
    将多个对象的可枚举属性拷贝到目标对象上,并且返回赋值后的目标对象。

        Object.defineProperties():

    Object.defineProperties()
    给对象定义属性,如果存在该属性,
    则用新定义的属性更新已存在的属性,
    如果不存在该属性,则添加该属性。

    4.ES6 继承  (逼格最高,也是未来的趋势,必学必用)

    知识点:
    class  类
    ES6给我们提供了class的语法糖,可以通过class来创建类
     1      class Person {//此行没有括号,在第二行constructor()传参
     2          constructor(name,age){
     3              this.name = name;
     4              this.age = age;
     5          }
     6          /*下面的写法就等同于把方法挂在原型上*/
     7          static say(){// 加了static 静态方法,只给类用的方法
     8              console.log('哈哈');
     9          }//方法和方法之间不用加逗号 ,
    10          say(){//动态方法,给实例使用的方法
    11              console.log(this.name);
    12          }
    13      }
    14  
    15      let p = new Person('成龙',20);
    16      p.say();//成龙

    声明子类 extends 父类名 就继承父类了

     1     class Coder extends Person {
     2         /*
     3             在子类constructor中添加属性的小技巧
     4 
     5             专属于子类的属性写在参数的前面,父类的属性放在后面
     6             这样一来,就能直接使用...arg
     7 
     8             ...arg
     9                 把函数中的多余的参数放入数组中体现出来。
    10 
    11         */
    12         constructor(job,...arg){
    13             // console.log(this)
    14             super(...arg); //等同于调用父类,把多余的参数(和父类一样的属性)放到super中,达到继承父类属性的目的
    15             /*
    16                 在继承里,写constructor必须写super
    17                 super下面才能使用this,super有暂存死区(super上面不能使用this,用了就报错)
    18             */
    19             this.job = job;//自己私有的属性,直接this点即可
    20             console.log(arg);
    21         }
    22         codeing(){
    23             console.log('敲代码');
    24         }
    25         say(){
    26             console.log('哈哈');
    27         }
    28 
    29     }
    30 
    31     let c = new Coder('前端','周杰伦',20);
    32     let p = new Person('张杰',30);
    33     // delete c.name;
    34     console.log(c);
    35     // c.say();
    36     // p.say();
    37     // c.codeing();
  • 相关阅读:
    基于Spring MVC的前后端分离开发
    vue 3.0 初体验 (项目搭建)及新特性
    ECharts介绍及使用方法
    jQuery获取Radio选择的Value值||两个select之间option的互相添加操作(jquery实现)
    如何在在网页上显示pdf文档
    Js获取当前日期时间及其它操作
    ASP.NET页面生命周期和asp.net应用程序生命周期
    ASP.NET请求处理过程
    IQueryable与IQEnumberable的区别
    leetcode 705 设计哈希映射
  • 原文地址:https://www.cnblogs.com/MrZhujl/p/9907445.html
Copyright © 2020-2023  润新知