【JavaScript】Class 类

Class

ES6 引入了 Class 这个概念,通过关键字 class,可以定义类

关键字 class 可以看作是构造函数的语法糖,class 的绝大部分功能都能通过构造函数实现


ES5 的构造函数

// 通过构造函数设置实例属性
function Person(name) {
    this.name = name;
};

// 为原型 Person.prototype 添加方法, 使得所有实例共享此方法
Person.prototype.showName = function () {
    return `名字: ${this.name}`;
};

const person = new Person("superman");
console.log(person.showName());

我们也可以通过 Object.assign() 方法给 Person.prototype 添加方法 / 属性

// 使用 Object.assign() 为 Person.prototype 添加方法
Object.assign(Person.prototype, {
    showName() {
        return `名字: ${this.name}`;
    },
});

Class 的使用

  • 构造方法 constructor 相当于 ES5 的构造函数,可以在 constructor 里面添加实例的属性
  • 可以在 class 里面直接编写方法,相当于为原型 Person.prototype 添加方法, 使得所有实例共享此方法
class Person {
    // 构造方法 constructor, 只要执行 new Person(), 构造方法就会被调用
    constructor(name) {
        this.name = name;
        console.log(`执行构造函数`);
    }

    // 普通方法, 相当于为原型 Person.prototype 添加方法, 使得所有实例共享此方法
    showName() {
        return `名字: ${this.name}`;
    }
};

const person = new Person(`superman`, 18);
console.log(person.showName());

class 的表达式写法:

const Person = class { // 匿名类
    constructor() {
        this.name = `superman`;
    }
    showName() {
        return `名字: ${this.name}`;
    }
};

const person = new Person();
console.log(person.showName());

构造方法 constructor

  • 通过 new 创建实例时,会自动调用类的构造方法 constructor
  • 一个类必须有构造方法 constructor,如果没有显式定义,JS 会默认添加一个空的构造方法
class Fn {}

// 等同于
class Fn {
    constructor() {}
}
关于构造方法的返回值
  • 构造方法 constructor 默认返回当前实例 this
  • 开发者也可以手动 return 值:
    如果返回 [引用类型数据],会覆盖默认返回值
    如果返回 [基本类型数据],则仍然返回当前实例 this
class Foo {
    constructor() {
        return { name: 'superman' }; // 返回一个对象
    };
};

const foo = new Foo();
console.log(foo); // { name: 'superman' }
console.log(foo instanceof Foo); // false
注意事项:
  • 类必须使用关键字 new 调用
class Foo {
    constructor() {
        return Object.create(null);
    };
};

Foo(); // TypeError: Class constructor Foo cannot be invoked without 'new'
  • 如果方法名要用变量,就要使用 [] 的表达式
let a = 'showName';

class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    };
    [a]() {
        return `名字:${this.name}`;
    };
};
console.log(typeof Person); // function

let per1 = new Person("superman", 18);
console.log(per1['showName']()); // 可通过 ['showName'] 调用
console.log(per1[a]()); // 也可以通过 [a] 调用
// console.log(per1.a()); // 不能通过 a 调用函数

既然 [] 内可以用字符串,那当然可以使用字符串拼接啦:

console.log(per1['show' + 'Name']()); // superman
  • 使用 ES5 的构造函数模拟类,会出现函数提升,因为构造函数本质上就是一个函数嘛

    使用 ES6 的 class 类,不会出现函数提升

let person = new Person(); // ReferenceError: Cannot access 'Person' before initialization

class Person {
    constructor() {
        this.name = "superman";
    };
};
let per1 = new Person();
console.log(per1); // Person {}

function Person() {};



getter & setter

  • get xxx():获取指定值时 自动调用
  • set xxx(xx):修改指定值时 自动调用
class Person {
    constructor(age) {
        this._age = age; // 下划线开头的属性, 为私有属性, 不能直接获取 (这是一个约定)
    }
    // getter;  getter 里面不要写其他语句, 会报错
    get age() {
        console.log('getter 已被调用');
        return this._age;
    }
    // setter
    set age(value) {
        console.log('setter 已被调用');
        this._age = value;
    }
};

const person = new Person(18);
console.log(person.age); // getter 已被调用    18
person.age = 21; // setter 已被调用
console.log(person.age); // getter 已被调用    21



静态方法

  • 静态方法:用关键字 static 修饰的方法。静态方法需要通过类名调用
class Person {
    fun() {
        console.log(this); // this 指向实例
    }
    static staticFun() {
        console.log(this); // this 指向类
    }
};

const person = new Person();
person.fun(); // 通过实例调用方法
Person.staticFun(); // 通过类名调用静态方法



类的继承

// 编写父类
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    showName() {
        console.log('父类的 showName 方法');
        return `名字: ${this.name}`;
    }
    showAge() {
        console.log('父类的 showAge 方法');
        return `年龄: ${this.age}`;
    }
};

// 编写子类
class Student extends Person {
    // 如果子类实例中没有独有的属性, 可以不用编写构造方法
    constructor(name, skill, age) {
        // 在子类的构造方法中, 必须先通过 super 调用父类的构造方法
        super(name, age);
        // 设置子类实例独有的属性
        this.skill = skill;
    }

    // 重写父类的方法
    showName() {
        // 在子类的普通方法中, 可以通过 super 调用父类的方法
        super.showName();
        // 编写其他逻辑代码
        console.log('子类的 showName 方法');
        return `名字: ${this.name}`;
    }

    // 编写子类的方法
    showSkill() {
        return `技能: ${this.skill}`;
    }
}

const stu = new Student("superman", "逃课", 18);

console.log(stu.name, stu.skill); // superman 逃课
console.log(stu.showSkill()); // 技能: 逃课
console.log(stu.showAge()); // 父类的 showAge 方法    年龄: 18
console.log(stu.showName()); // 父类的 showName 方法    子类的 showName 方法    名字: superman
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
JavaScript中,使用class语法定义时,可以通过在构造函数中直接定义属性来定义成员属性,也可以使用静态属性来定义成员属性。 成员属性是每个实例对象独有的属性,可以通过在构造函数中使用this关键字来定义。例如,以下代码定义了一个Person,其中的name和age属性是成员属性: ``` class Person { constructor(name, age) { this.name = name; this.age = age; } } var person1 = new Person("John", 30); console.log(person1.name); // 输出:John console.log(person1.age); // 输出:30 ``` 成员属性是所有实例对象共享的属性,可以使用静态属性来定义。例如,以下代码定义了一个Animal,其中的count属性是成员属性: ``` class Animal { static count = 0; constructor(name) { this.name = name; Animal.count++; } } var animal1 = new Animal("cat"); var animal2 = new Animal("dog"); console.log(Animal.count); // 输出:2 ``` 在上面的代码中,count属性被定义为Animal的静态属性,它可以在的任何方法中访问,而且所有Animal的实例共享该属性。在构造函数中,每次创建Animal对象时,都会将count属性加1,从而实现对象计数的功能。 需要注意的是,成员属性和成员属性是有区别的,它们的作用域和生命周期不同。成员属性是每个实例独有的,而成员属性是所有实例共享的。在使用时需要根据需要进行选择。同时,在class语法中,成员属性必须使用static关键字进行定义,成员属性则不需要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JS.Huang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值