当前位置: 首页 > article >正文

33、class

 什么是class

(1). 问题

旧js中每定义一种类型,都要定义两部分: 构造函数+原型对象。但是,旧js中,构造函数和原型对象在写法上是分离的。不符合封装的要求。

(2). 解决

今后,只要创建一种类型,都要用class{}包裹构造函数+原型对象方法

(3). 什么是class

集中存储一个类型的构造函数和原型对象方法的程序结构。

(4). 如何: 3步

a. 用class{}包裹原构造函数和原型对象方法

b. 原构造函数名/类型名提升为class的名字,原构造函数必须更名为constructor。

c. 所有直接定义在class中的方法,默认都是保存在原型对象中的。

    无需添加类型名.prototype前缀

    也无需=function

(5). 其实class就是新瓶装旧酒,换汤不换药。虽然写法上改成了class和简化版但是本质上还是构造函数+原型对象创建子对象时,还是new 类型名(属性值列表);

 (6). 示例: 定义class保存学生类型的构造函数和原型对象方法: 

 3_class.html

<script>

    class Student{

      //构造函数

      constructor(sname,sage){

        this.sname=sname;

        this.sage=sage;

      }

      //自动放入原型对象中保存

      intr(){

        console.log(`I'm ${this.sname}, I'm ${this.sage}`);

      }

    }

    var lilei=new Student("Li Lei",11);

    console.log(lilei);

    lilei.intr();

  </script>

运行结果: 

Student {sname: "Li Lei", sage: 11}
  sage: 11
  sname: "Li Lei"
  __proto__:
    constructor: class Student
    intr: ƒ intr()
    __proto__: Object

I'm Li Lei, I'm 11

<script>

        function student(uname,uage){

            this.uname=uname;

            this.uage=uage;

        }

        student.prototype.intr=function(){

            console.log(`i'm ${this.uname}`);

        }

        var lilei=new student("lilei",11);

        console.log(lilei);

</script>

class中如何保存共有属性

问题

如果多个子对象共用的相同的属性值,应该放在那里?

a. 旧js中,是和共有方法一起放在原型对象中

b. ES6 class中: 

1). 问题

虽然直接在class中定义的方法,都默认保存在原型对象中。但是直接在class中定义的属性,却不会成为共有属性,不会保存在原型对象中。而是成为每个子对象的自有属性。

2). 解决

为了和其它主流开发语言尽量一致,ES6的class放弃了在原型对象中保存共有属性的方式。而是改为用静态属性保存!

    i. 什么是: 不需要创建子对象,单靠类型名就可直接访问的属性,就称为静态属性

    ii. 何时: 今后,在ES6中,如果希望所有子对象,都可使用一个共同的属性值时,都要用静态属性代替原来的原型对象属性

    iii. 如何定义静态属性: 

      class 类型名{
  static 共有属性名=属性值

        ...

        ...
      }

    iv. 如何访问静态属性: 

    坑: 错误: this.静态属性

    正确: 类型名.静态属性

v. 原理

    标有static的静态属性,都是保存在构造函数对象身上。因为构造函数在程序中不会重复!所以,静态属性,也不会重复!任何是否,任何地点,访问一个类型的静态属性,永远访问的都是同一份

vi. 示例: 使用静态属性替所有子对象保存共用的班级名

4.1_class_static.html

<script>

    //想定义学生类型,描述所有学生的统一结构和功能

    class Student{

      //定义静态属性className,可以全班同学共用一个

      static className="初一2班"

      constructor(sname, sage){

        this.sname=sname;

        this.sage=sage;

      }

      // className="初一2班" //不是共有,会变成自有属性

      //默认保存在原型对象中

      intr(){

        console.log(`I'm ${this.sname}, I'm ${this.sage}, I'm from ${Student.className}`);

      }

    }

    //创建一个学生类型的对象

    var lilei=new Student("Li Lei",11);

    var hmm=new Student("Han Meimei",12);

    console.log(lilei);

    console.log(hmm);

    lilei.intr();

    hmm.intr();

    //过了一年,两个学生都升级

    Student.className="初二2班"

    lilei.intr();

    hmm.intr();

    console.log(Student);//不行!默认输出的是Student构造函数的函数体,不是对象结构

    console.dir(Student);//不输出函数的内容,而是输出对象在内存中的存储结构

</script>

运行结果: 

<script>

   class Student {

        constructor(snamesage) {

           this.sname = sname;

           this.sage = sage;

        }

        static className = "初一二班";

        intr() {

            console.log(`你好,我是${this.sname},

我今年${this.sage},我来自${Student.className}`);

            }

        }

        console.dir(Student);            

var lilei = new Student("lilei"11);

        console.log(lilei);         

两种类型间的继承

a. 问题

定义多个class时,发现多个class之间拥有部分相同的属性结构和方法定义。

b. 解决

今后只要发现多个class之间包含部分相同的属性结构和方法定义时都可以额外定义一个父类型class替多个class集中保管相同部分的属性结构和方法定义然后再让多个class继承这个父类型class

c. 如何: 2大步

1). 先额外定义一种新的class

    i. class名应该涵盖多个子集class的范围

    ii. 多个class相同部分的属性结构,集中保存到父类型class的构造函数(constructor)中

    iii. 多个class相同部分的方法定义,集中保存到付类型class中
    iv. 多个class中不再需要包含相同部分的属性结构和方法了。

2). 让子类型class继承父类型class

 设置子类型的原型对象继承父类型的原型对象

    i. class 子类型 extends 父类型{ ... }

                扩展/继承

   相当于Object.setPrototypeOf(子类型原型对象, 父类型原型对象);

但是,这样只能保证子类型的对象可以使用父类型class原型对象中的方法依然无法为子类型的对象添加公共部分的属性结构。因为公共部分的属性结果不在父类型class的原型对象中,而是在父类型class的构造函数里。所以,

    ii. 还必须在子类型构造函数中,先调用super()关键字自动调用父类型class中的constructor()构造函数,并自动执行父类型class的构造函数中的代码。结果父类型的构造函数将公共部分的属性结构添加到子类型的对象身上。——结果: 最终子类型的子对象是由2个构造函数通力合作创建出来的。

什么是super

是extends附赠给我们的,自动代表父类型class中constructor构造函数的关键字。调用super()等效于调用父类型class中的constructor.

相当于执行{this.x=x;this.y=y}

  d. 示例: 定义class描述飞机大战游戏中的敌机和降落伞类型,同时避免属性和方法重复定义

  4_class_extends.html

<script>

//定义父类型class,替所有子类型class集中保管相同部分的属性结果和方法定义

    class Enemy{

      constructor(x,y){

        this.x=x;

        this.y=y;

      }

      fly(){

        console.log(`飞到x=${this.x},y=${this.y}位置`)

      }

    }

    //定义子类型继承父类型

    class Plane extends Enemy{//仅继承原型对象

      constructor(x,y,score){

        super(x,y);

        //this.x=x;

        //this.y=y;

        this.score=score;

      }

      //自动就会保存进Plane原型对象中

      getScore(){

        console.log(`击落敌机得${this.score}分`)

      }

    }

    class San extends Enemy{

      constructor(x,y,award){

        super(x,y);

        this.award=award;

      }

      getAward(){

        console.log(`击落降落伞,得${this.award}奖励`)

      }

    }

    //创建子类型子对象

    var p1=new Plane(50,100,5);

    var s1=new San(20,80,"1 life");

    console.log(p1);

    console.log(s1);

    p1.fly();//爷爷的

    p1.getScore();//爸爸的

    s1.fly();

    s1.getAward();

  </script>

  运行结果: 

Plane {x: 50, y: 100, score: 5}
  score: 5
  x: 50
  y: 100
  __proto__:
    constructor: class Plane
    getScore: ƒ getScore()
    __proto__:
      constructor: class Enemy
      fly: ƒ fly()
      __proto__: Object

San {x: 20, y: 80, award: "1 life"}

  award: "1 life"

  x: 20

  y: 80

  __proto__:

    constructor: class San

    getAward: ƒ getAward()

    __proto__:

      constructor: class Enemy

      fly: ƒ fly()

      __proto__: Object

飞到x=50,y=100位置

击落敌机得5分

飞到x=20,y=80位置

击落降落伞,得1 life奖励


http://www.kler.cn/a/591790.html

相关文章:

  • [本周五题]Javascript面试常考题手撕场景UR缓存、new关键字、大数相加、最长递增子序列、高并发请求、大文件上传和WebWorks
  • 基于FPGA的3U机箱模拟量高速采样板ADI板卡,应用于轨道交通/电力储能等
  • 精准git动图拆解​
  • React第三十章(css原子化)
  • Android 15 获取网络切片信息的标准接口
  • vue3+elementPlus使用vuedraggable实现照片墙拖拽调整位置
  • 【设计模式】3W 学习法全面解析 7 大结构型模式:Java 实战 + 开源框架应用
  • 合React宝宝体质的自定义防抖hook
  • 安全地自动重新启动 Windows 资源管理器Bat脚本
  • css3有哪些新属性
  • 计算机网络-综合布线系统
  • trae和Spring Boot Java 项目 ruoyi框架
  • STM32---FreeRTOS软件定时器
  • 关于非线性优化小记
  • 半导体制造行业的现状 内检LIMS系统在半导体制造的应用
  • Spring Cloud 中的服务注册与发现: Eureka详解
  • mybatis集合映射association与collection
  • WebForms HTML:深入理解与高效应用
  • RS-232与TTL、CMOS的区别
  • 软件工程:数据字典