Class类基础知识梳理

Class类基础知识梳理

1、什么是Class类

  • 在ES6中,class (类)作为对象的模板被引入,可以通过 class 关键字定义类。
  • class 的本质是 function。
  • 它可以看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法。

2、怎么声明一个类

注意:不可重复声明

// 创建一个Person父类
class Person {
    // constructor 方法是类的默认方法,创建类的实例化对象时被调用。
    constructor(name, age) {
        // 构造器中的this是谁?—— 类的实例对象
        console.log("Person-constructor",this)
        // 实例属性
        this.name = name;
        this.age = age;
    }
}

3、类的实例化

  • class 的实例化必须通过 new 关键字。
  • 类定义不会被提升,这意味着,必须在访问前对类进行定义,否则就会报错。
// 创建一个Person父类
class Person {
    // constructor 方法是类的默认方法,创建类的实例化对象时被调用。
    constructor(name, age) {
        // 构造器中的this是谁?—— 类的实例对象
        console.log("Person-constructor",this)
        // 实例属性
        this.name = name;
        this.age = age;
    }
}

let p1 = new Person();
let p2 = new Person();
console.log('p1、p2是否共享原型对象',p1._proto_ == p2._proto_)
// 用于验证constructor中this是否就是new出来的实例对象
p1.sex = 'man'

image-20210810100540726

4、类中的方法

  • 原型方法(一般方法):写在原型中的方法可以被所有的实例共享, 实例化的时候不会在实例内存中再复制一份,占有的内存消耗少。ES6 中,prototype 仍旧存在,虽然可以直接在类中定义方法,但是其实方法还是定义在 prototype 上的。
  • 静态方法:在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
  • 实例方法:对象方法需要通过实例化对象去调用 。
// 创建一个Person父类
        class Person {
            // constructor 方法是类的默认方法,创建类的实例化对象时被调用。
            constructor(name, age) {
                // 构造器中的this是谁?—— 类的实例对象
                console.log("Person-constructor",this)
                // 实例属性
                this.name = name;
                this.age = age;
                // 实例方法
                this.sleep = () => {
                    console.log(this.name + "正在睡觉")
                }
            }
 
            /*
                注意:
                1、如果静态方法包含this关键字,这个this指的是类,而不是实例。
                   类中一般方法:类的方法内部如果含有this,它默认指向类的实例。
                2、静态方法不能被实例调用,只能通过类来调用。
            */
            // 原型方法(一般方法)
            work(a, b) {
                console.log('原型方法中的this', this)
                console.log('打工人,冲~~');
                console.log('工作', a+b);
            }
 
            // 静态方法,
            //在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
            static study(a, b) {
                console.log('静态方法中的this', this)
                console.log('学习码代码呀~~');
                console.log('study', a+b);
            }
        }
 
        let p1 = new Person('张三', 18);
        let p2 = new Person('李四', 19);
        console.log('p1、p2是否共享原型对象',p1._proto_ == p2._proto_)
        p1.work(1,1)
        // 用于验证constructor中this是否就是new出来的实例对象
        p1.sex = 'man'
        p2.work(2,2)
        p1.sleep()
        // 下面这种调用会报错
        // Person.sleep()
        // 下面这种调用会报错,study方法是一个静态方法,可以直接在Person类上调用(Person.study()),而不是在Person类的实例上调用
        // p1.study(1,2)
        Person.study(1,2)

直接使用类调用对象方法,会报如下错误:
image-20210810102634690
上方demo执行结果如下:
image-20210810104148836
总结

  • class的一般方法定义在类的原型上,实例会继承原型上的所有方法。
  • class的静态属性和静态方法定义在类上,实例不会继承静态属性和静态方法。访问静态属性或调用静态方法,均通过类名调用。

5、类中的属性

  • 公共属性:定义在原型上,所有实例会继承原型上的属性
  • 静态属性class 本身的属性,即直接定义在类内部的属性( Class.propname ),不需要实例化。 ES6 中规定,Class 内部只有静态方法,没有静态属性。
  • 实例属性:定义在实例对象( this )上的属性。
// 创建一个Person父类
class Person {
    // constructor 方法是类的默认方法,创建类的实例化对象时被调用。
    constructor(name, age) {
        // 构造器中的this是谁?—— 类的实例对象
        console.log("Person-constructor",this)
        // 实例属性
        this.name = name;
        this.age = age;
    }
 
    // 静态属性
    static healthy = true
}
// 公共属性
Person.prototype.country = 'china';
let p1 = new Person('张三', 18);
let p2 = new Person('李四', 19);
console.log('Person调用静态属性', Person.healthy)
console.log('p1调用静态属性', p1.healthy)

image-20210810110804958

6、类中的私有属性与私有方法

私有方法和私有属性,是只能在类的内部访问的方法和属性,外部不能访问。
class加了私有方法/私有属性。方法是在方法/属性名之前,使用#表示。

// 创建一个Person父类
class Person {
    // constructor 方法是类的默认方法,创建类的实例化对象时被调用。
    constructor(name, age) {
        // 构造器中的this是谁?—— 类的实例对象
        console.log("Person-constructor",this)
        // 实例属性
        this.name = name;
        this.age = age;
        // 实例方法
        this.sleep = () => {
            console.log(this.name + "正在睡觉")
        }
    }
    // 定义私有变量
    #count = 0
    // 定义私有方法
    #sum() {
        console.log('我是类的私有方法')
    }
    /*
    	注意:
            1、如果静态方法包含this关键字,这个this指的是类,而不是实例。
               类中一般方法:类的方法内部如果含有this,它默认指向类的实例。
            2、静态方法不能被实例调用,只能通过类来调用。
    */
    // 原型方法(一般方法)
    work(a, b) {
        console.log('原型方法中的this', this)
        console.log('打工人,冲~~');
        console.log('工作', a+b);
        console.log("调用私有变量", this.#count + 1)
        console.log("调用私有方法", this.#sum())
    }
}
let p1 = new Person('张三', 18);
let p2 = new Person('李四', 19);
p1.work(1,1)
//下方两行代码直接调用私有变量/私有方法不可取
// console.loh('p1.#count', p1.#count)
//console.log('p1.#sum()', p1.#sum())

若直接使用类/实例调用会报如下错
image-20210810113449908
上方demo执行结果如下:
image-20210810113343340

7、类的继承

7.1 extends与super
  • 通过 extends实现类的继承
  • 子类 constructor 方法中必须有 super ,且必须出现在 this 之前。
    • 调用父类构造函数,只能出现在子类的构造函数。
    • 调用父类方法, super 作为对象,在普通方法中,指向父类的原型对象,在静态方法中,指向父类
//创建一个Student类,继承于Person类
class Student extends Person {
    constructor(){
        super();
        // 调用父类普通方法
        console.log(super.work());
    }
    static staticStudy(){
        // 调用父类静态方法
        super.study();
    }
}
console.log(Student.staticStudy())

上方demo执行结果如下:
image-20210810122617077

7.2 关于constructor

类中的构造器不是必须要写的,要对实例进行一些初始化的操作,如添加指定属性时才写。

//创建一个Student类,继承于Person类
class Student extends Person {
    speak(){
       //speak方法放在了哪里?——类的原型对象上,供实例使用
       //通过Person实例调用speak时,speak中的this就是Person实例
       console.log(`我叫${this.name}, 我年龄是${this.age}, 我读的是${this.grade}年级`);
    }
}
 
let stu = new Student('张三', 18, '高三')
console.log('stu', stu.speak())

上方demo执行结果如下,子类中没有写constructor,代码运行并没有报错,只是由于没有在constructor中进行一些初始化操作,导致获取到的grade为undefined,而name跟age由于在父类中的构造器中已经接收,所以子类继承了父类的构造器,拿来即用,所以能打印出值
在这里插入图片描述
那如果想获取到年级我们该怎么办呢?看如下代码:

//创建一个Student类,继承于Person类
class Student extends Person {
    constructor(name,age,grade){
        super(name, age); //调用父类构造器
        this.grade = grade
    }
    speak(){
        //speak方法放在了哪里?——类的原型对象上,供实例使用
        //通过Person实例调用speak时,speak中的this就是Person实例
        console.log(`我叫${this.name}, 我年龄是${this.age}, 我读的是${this.grade}年级`);
    }
}
let stu = new Student('张三', 18, '高三')
console.log('stu', stu.speak())
7.3 重写从父类继承过来的方法
//创建一个Student类,继承于Person类
class Student extends Person {
    constructor(name,age,grade){
        super(name, age);
        this.grade = grade
        // 调用父类普通方法
        console.log(super.work());
    }
    static staticStudy(){
        // 调用父类静态方法
        super.study();
    }
    speak(){
        //speak方法放在了哪里?——类的原型对象上,供实例使用
        //通过Person实例调用speak时,speak中的this就是Person实例
        console.log(`我叫${this.name}, 我年龄是${this.age}, 我读的是${this.grade}年级`);
        this.work();
    }
    //重写从父类继承过来的方法
    work(){
        //work方法放在了哪里?——类的原型对象上,供实例使用
        //通过Student实例调用work时,work中的this就是Student实例
        console.log('要努力工作~~');
    }
}
let stu = new Student('张三', 18, '高三')
console.log('stu', stu.speak())

image-20210810135729522
image-20210810135317013

8、类中使用赋值语句

// 创建一个Person父类class Person {    // constructor 方法是类的默认方法,创建类的实例化对象时被调用。    constructor(name, age) {        // 构造器中的this是谁?—— 类的实例对象        console.log("Person-constructor",this)        // 实例属性        this.name = name;        this.age = age;    }     // 赋值语句    // 类中可以直接写赋值语句,如下代码的含义是:给Person的实例对象添加一个属性,名为state,值为在职    state = '在职'}let p1 = new Person('张三', 18);

image-20210810140743557

9、总结:

  • 类中的构造器不是必须要写的,要对实例进行一些初始化的操作,如添加指定属性时才写。
  • 如果A类继承了B类,且A类中写了构造器,那么A类构造器中的super是必须要调用的。
  • 类中所定义的方法,都放在了类的原型对象上,供实例去使用。
  • this指向问题
    • 构造器中的this是谁? 答:类的实例对象
    • 静态方法中的this是谁?答:这个this指的是类,而不是实例
    • 一般方法中的this是谁? 答:类的一般方法内部如果含有this,它默认指向类的实例。
    • 箭头函数中的this是谁?答:箭头函数没有自己的this,它只会从自己的作用域链的上一层继承this。不同于在普通函数里,this的值在定义时是不明确的,要等到调用时才能确定,谁调用就指向谁。在箭头函数中,this是在创建时就已经确定了,箭头函数内部的this就是外层代码块的this。
      ​ 注意:箭头函数内部的this是词法作用域,由上下文确定
      image-20210810142404295
      完整的代码如下:
<!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>Class 类</title>
</head>
<body>
    <script>
        /*
            在ES6中,class (类)作为对象的模板被引入,可以通过 class 关键字定义类。
            class 的本质是 function。
            它可以看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法。
        */
 
        // 创建一个Person父类
        class Person {
            // constructor 方法是类的默认方法,创建类的实例化对象时被调用。
            constructor(name, age) {
                // 构造器中的this是谁?—— 类的实例对象
                console.log("Person-constructor",this)
                // 实例属性
                this.name = name;
                this.age = age;
                // 实例方法
                this.sleep = () => {
                    console.log(this.name + "正在睡觉")
                }
            }
 
            // 赋值语句
            // 类中可以直接写赋值语句,如下代码的含义是:给Person的实例对象添加一个属性,名为state,值为在职
            state = '在职'
            // 静态属性
            static healthy = true
 
            // 定义私有变量
            #count = 0
            // 定义私有方法
            #sum() {
                console.log('我是类的私有方法')
            }
            /*
                注意:
                1、如果静态方法包含this关键字,这个this指的是类,而不是实例。
                   类中一般方法:类的方法内部如果含有this,它默认指向类的实例。
                2、静态方法不能被实例调用,只能通过类来调用。
            */
            // 原型方法(一般方法)
            work(a, b) {
                console.log('原型方法中的this', this)
                console.log('打工人,冲~~');
                console.log('工作', a+b);
                console.log("调用私有变量", this.#count + 1)
                console.log("调用私有方法", this.#sum())
            }
 
            // 静态方法,
            //在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
            static study(a, b) {
                console.log('静态方法中的this', this)
                console.log('学习码代码呀~~');
                console.log('study', a+b);
            }
        }
 
        //创建一个Student类,继承于Person类
        class Student extends Person {
            constructor(name,age,grade){
                super(name, age);
                this.grade = grade
                // 调用父类普通方法
                console.log(super.work());
            }
            static staticStudy(){
                // 调用父类静态方法
                super.study();
            }
            speak(){
                //speak方法放在了哪里?——类的原型对象上,供实例使用
                //通过Person实例调用speak时,speak中的this就是Person实例
                console.log(`我叫${this.name}, 我年龄是${this.age}, 我读的是${this.grade}年级`);
                this.work();
                console.log(this.running)
            }
            //重写从父类继承过来的方法
            work(){
                //work方法放在了哪里?——类的原型对象上,供实例使用
                //通过Student实例调用work时,work中的this就是Student实例
                console.log('要努力工作~~');
            }
 
            //自定义方法————要用赋值语句的形式+箭头函数
            running = () => {
                console.log('箭头函数中的this', this)
            }
        }
 
        // 公共属性
        Person.prototype.country = 'china';
        // // 下方这种写法也能定义静态属性
        Person.reading = '马克思主义';
        let p1 = new Person('张三', 18);
        let p2 = new Person('李四', 19);
        console.log('Person调用静态属性', Person.healthy)
        console.log('p1调用静态属性', p1.healthy)
        console.log('p1、p2是否共享原型对象',p1._proto_ == p2._proto_)
        p1.work(1,1)
        // 用于验证constructor中this是否就是new出来的实例对象
        p1.sex = 'man'
        p2.work(2,2)
        p1.sleep()
        // 下面这种调用会报错
        // Person.sleep()
        // 下面这种调用会报错,study方法是一个静态方法,可以直接在Person类上调用(Person.study()),而不是在Person类的实例上调用
        // p1.study(1,2)
        Person.study(1,2)
        //下方两行代码直接调用私有变量/私有方法不可取
        // console.loh('p1.#count', p1.#count)
        // console.log('p1.#sum()', p1.#sum())
 
        console.log(Student.staticStudy())
 
        let stu = new Student('张三', 18, '高三')
        console.log('stu', stu.speak())
        console.log('箭头函数中', stu.running())
    </script>
</body>
</html>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,我无法回答关于2023年的问题,因为我无法提供未来的信息。但是,如果你对Java基础知识点有兴趣,我可以为你提供一些相关的信息。Java基础知识点包括数据类型、变量、运算符、控制流程、数组、字符串、面向对象编程等。你可以参考Java基础教程系列,其中包含了Java基础知识点、Java8新特性、Java集合、Java多线程等内容,可以帮助你轻松学习Java编程。\[1\]另外,Javac是Java编译器程序的一部分,负责将Java源代码编译成字节码文件,也就是class文件,供Java虚拟机(JVM)执行。\[2\]Java分为三个体系,分别是Java SE(标准版)、Java EE(企业版)和Java ME(微型版),每个体系都有不同的用途和应用领域。\[3\]希望这些信息对你有帮助! #### 引用[.reference_title] - *1* [java基础知识点](https://blog.csdn.net/guorui_java/article/details/120317300)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Java基础知识点整理,推荐收藏!](https://blog.csdn.net/weixin_42599558/article/details/114148399)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值