js 类

110 阅读4分钟

前言

学习了很多次类但是总是忘记,还是需要记笔记

类是什么

  类就是定义对象的模板,类决定了一个对象中有什么属性和方法
  使用class关键字来定义类
  

怎么定义一个类

  class Figure { //创建一个人物类 首字母大写
            name = "张三";
            age = 18
            run() {
                console.log("跑的飞快");
            }
            constructor(canshu) { //类的构造函数,里面放的是类的属性.new的过程中会调用这个方法
                console.log(canshu);
            }
        }
        let fig1 = new Figure("one"); 
        let fig2 = new Figure("two  ");
        console.log(fig1===fig2);  //false 每次new都是新的内存空间
        console.log(fig1, fig2);   
        fig1.run()

image.png

我们也可以利用构造函数的参数来设置不同的对象的值

        class Figure { //创建一个人物类 首字母大写
            // name = "张三";
            // age = 18
            // run() {
            //     console.log("跑的飞快");
            // }
            constructor(name,age) { //类的构造函数,里面放的是类的属性.new的过程中会调用这个方法
                this.name = name;
                this.age  = age
            }
        }
        let fig1 = new Figure("孙悟空",1223)
        let fig2 = new Figure("猪八戒",1223)
        console.log(fig1, fig2); 

image.png

类的this

this是比较复杂的东西,这种东西不好理解所以尽量避免使用,但是必须要会.首先js中this是谁调用指向谁,但是严格模式下的函数式调用会出现不指向全局而是undefined 类中的所有代码都在严格模式下执行

        class MyClass {
            say(){
                console.log(this);
            }
        }
        let one = new MyClass() //创建一个对象
        one.say()//以方法形式执行 指向当前实例 MyClass {}
        let two = one.say 
        two()//函数式调用 undefined  严格模式

说明:要注意如果类中的this指向是不固定的.类中的函数以方法形式调用的话一般会指向当前实例.但是函数形式执行将会指向全局但是严格模式下会指向undefined.

有时候我们需要方法中的thsi是固定的,这时候我们使用箭头函数

        class MyClass {
            say = () =>{ //箭头函数的形式
                console.log(this);
            }
        }
        let one = new MyClass() //创建一个对象
        one.say()//恒定指向当前实例
        let two = one.say 
        two()//恒定指向当前实例

image.png

类的继承

神马是继承,简单说就是继承写好的代码懒得重复写了.子类继承父类

    class Animal {
            constructor(name, age) {
                this.name = name;
                this.age = age;
            }
            sayHello() {
                console.log("动物再叫");
            }
        }
        class Dog extends Animal { // 子类继承父类

        }
        class Cat extends Animal { // 子类继承父类

        }
        class Birds extends Animal { // 子类继承父类

        }
        let dog = new Dog("狗",12)
        console.log(dog); 
        let cat = new Cat("猫",3)
        console.log(cat);
        let birds = new Birds("鸟",1)
        console.log(birds);

image.png

说明:在子类未定义name 和age的时候继承了父类的属性.继承使用extends关键字,子类在前父类在后,可以简单理解为复制了父类的代码在子类的模块里面

        class Animal {
            constructor(name, age) {
                this.name = name;
                this.age = age;
            }
            sayHello() {
                console.log("动物再叫");
            }
        }
        class Dog extends Animal { // 子类继承父类

        }
        class Cat extends Animal { // 子类继承父类

        }
        class Birds extends Animal { // 子类继承父类

        }
        let dog = new Dog("狗",12)
        dog.sayHello() 
        // console.log(dog); 
        let cat = new Cat("猫",3)
        cat.sayHello()
        // console.log(cat);
        let birds = new Birds("鸟",1)
        birds.sayHello()
        // console.log(birds);

image.png

子类重写父类方法

这里都调用了父类的方法,我们不想使用的话可以自己重写父类的方法,调用方法的时候会先查找子类是否有这个方法如果没有才会去父类调用

        class Dog extends Animal { // 子类继承父类
            sayHello(){
                console.log("汪汪");  //这里我们重写一下父类方法
            }
        }

image.png

子类添加新的属性

子类添加新的属性的时候要第一时间调用父类的构造函数否则报错!并且带上父类的参数否则无法传参给父类

    class Animal {
            constructor(name, age) {
                this.name = name;
                this.age = age;
            }
            sayHello() {
                console.log("动物再叫");
            }
        }
   class Dog extends Animal { // 子类继承父类
            constructor(name, age,number) {  //子类添加新的属性需要第一时间调用父类构造函数
                super(name,age); //通过super方法调用父类,注意必须写上父类的形参否则undefined
                this.number  = number;
            }
            sayHello(){
                console.log("汪汪");
            }
        }
          let dog = new Dog("狗",12,3)
          console.log(dog.name,dog.age,dog.number); //结果如下图

image.png

补充! 类的静态属性方法以及实例属性和方法

我们以上的方式都是实例的形式调用类的方法类的属性都需要new,只能通过实例来调用而不是通过类直接调用,而直接通过类调用的方法和属性称为静态方法!!注意静态方法中的this指向类本身而不是实例

   class Lei {
            name = "John";
            run() {
                console.log('跑起来');
            }
        }
        let shili =  new Lei();
        shili.run() //跑起来  这是实例方法
        Lei.run() //Lei.run is not a function 直接通过类调用会报错

上面的代码显示了类的实例方法类无法直接调用的情况,那么怎么能直接调用呢?两种方法,一直是通过.来新增属性或方法 另一种是static (英文翻译:静的)关键字加到方法或者属性前 注意这种方法会让实例无法访问该属性或方法

        class Lei {
            static name = "John";  //静态方法   
            static run() {
                console.log('跑起来');
            }
        }
        let shili = new Lei();
        Lei.run()  //类直接调用
        Lei.add =  function (){  //类直接通过.的方式新增方法也只能通过类直接调用
            console.log("加加加");
        }
        Lei.add()//加加加
        shili.run() //报错