ES6之类(class)和继承

本文深入讲解ES6中新增的Class语法,包括构造方法、方法定义、变量方法名、this指向问题、静态方法、getter和setter、继承机制及注意事项。通过对比传统面向对象编程方式,阐述Class带来的便利和变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原来我们写面向对象编程,都是在通过构造函数,然后在原型上写的,比如:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  Person.prototype.getName = function () {
    return this.name;
  }
  Person.prototype.getAge = function () {
    return this.age;
  }
  function Person (name, age) {
    this.name = name;
    this.age = age;
  }
  let person = new Person ('ReSword', 21);
  console.log(person.getName(), person.getAge());
</script>
</html>

当然我们也可以通过Object.assign方法

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  // Person.prototype.getName = function () {
  //   return this.name;
  // }
  // Person.prototype.getAge = function () {
  //   return this.age;
  // }
  Object.assign(Person.prototype, {
    getName () {
      return this.name;
    },
    getAge () {
      return this.age;
    }
  });
  function Person (name, age) {
    this.name = name;
    this.age = age;
  }
  let person = new Person ('ReSword', 21);
  console.log(person.getName(), person.getAge());
</script>
</html>

这样也是可以的

接下里介绍ES6中新增的class方法

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  class Person {
    constructor (name, age) { //构造方法(函数),调用new,自动执行
      console.log(name, age);
    }
  }

  let person = new Person('ReSword', 21);
</script>
</html>

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  class Person {
    constructor (name, age) { //构造方法(函数),调用new,自动执行
      this.name = name;
      this.age = age;
    }
    getName () {
      return this.name;
    }
    getAge () {
      return this.age;
    }
  }
  console.log(typeof(Person));
  let person = new Person('ReSword', 21);
  console.log(person.getName(), person.getAge());
</script>
</html>

上面的Person使用的函数声明的方式,也可以是使用函数变量的方式来使用calss

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  const Person = class {
    constructor (name, age) { //构造方法(函数),调用new,自动执行
      this.name = name;
      this.age = age;
    }
    getName () {
      return this.name;
    }
    getAge () {
      return this.age;
    }
  }
  console.log(typeof(Person));
  let person = new Person('ReSword', 21);
  console.log(person.getName(), person.getAge());
</script>
</html>

这种方式也是可以的

--------------------------------------------------------------------------------------------

下面说明class中的方法名可以使用变量来代替

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  let AAA = 'BBB';
  const Person = class {
    constructor (name, age) { //构造方法(函数),调用new,自动执行
      this.name = name;
      this.age = age;
    }
    getName () {
      return this.name;
    }
    getAge () {
      return this.age;
    }
    AAA () {
      return 'AAA-function';
    }
  }
  let person = new Person('ReSword', 21);
  console.log(person.AAA());
</script>
</html>

这样子我们去访问AAA 是有这函数的

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  let AAA = 'BBB';
  const Person = class {
    constructor (name, age) { //构造方法(函数),调用new,自动执行
      this.name = name;
      this.age = age;
    }
    getName () {
      return this.name;
    }
    getAge () {
      return this.age;
    }
    [AAA]() {
      return 'AAA-function';
    }
  }
  let person = new Person('ReSword', 21);
  console.log(person.BBB());
</script>
</html>

在我们加了 [] 之后,再去看

他会提示你AAA不是一个函数

我们去Person.prototype中查看

所以我们改成BBB

在我们改成BBB之后,

就可以运行到函数了

这其实就是JS的基础,我们知道后缀点和方括号都可以调用属性,但是后缀点是不能跟变量的,但是方括号可以

--------------------------------------------------------------------------------------------

还有就是class没有预解析,即下面这种写法是错误的

-------------------------------------------------------------------------------------

下面说明class中this指向的问题

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  class Person {
    constructor (name, age) {
      this.name = name;
      this.age = age;
    }
    getName () {
      console.log('this: ', this);
      return this.name;
    }
  }
  let person = new Person ('ReSword', 21);
  let {getName} = person;
  console.log(getName());
</script>
</html>

这里是因为你将Person中方法提取了出来,那么这里的this就会指向运行环境,所以造成运行失败

解决方法1:

调用bind方法,将getName绑定到对象上

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  class Person {
    constructor (name, age) {
      this.name = name;
      this.age = age;
      this.getName = this.getName.bind(this);
    }
    getName () {
      console.log('this: ', this);
      return this.name;
    }
  }
  let person = new Person ('ReSword', 21);
  let {getName} = person;
  console.log(getName());
</script>
</html>

解决方法2:

使用箭头函数

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  class Person {
    constructor (name, age) {
      this.name = name;
      this.age = age;
      this.getName = () => {
        console.log('this: ', this);
        return this.name;
      }
    }
  }
  let person = new Person ('ReSword', 21);
  let {getName} = person;
  console.log(getName());
</script>
</html>

------------------------------------------------------------------------------------------------

class里面还新增了两个函数getter和setter

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  class Person {
    constructor (name, age) {
      this.name = name;
      this.age = age;
    }
    get work () {
      return 'gettter'
    }
    set work (value) {
      console.log('setter: ' + value);
    }
  }
  let person = new Person ('ReSword', 21);
  person.work = 'student';//调用set
  console.log(person.work);//调用get
</script>
</html>

get和set一般用于封装底层框架

-------------------------------------------------------------------------------------------------

class里的静态方法:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  class Person {
    constructor (name, age) {
      this.name = name;
      this.age = age;
    }
    static fun () {
      return 'this is a static function';
    }
  }
  console.log(Person.fun());
</script>
</html>

----------------------------------------------------------------------------------------------

class里面的继承

我们先来看原JS的继承方法(即原型链)

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  Person.prototype.getName = function () {
    return this.name;
  }
  function Person (name, work) {
    this.name = name;
    this.work = work;
  }
  Student.prototype = new Person ();//继承方法
  function Student (name, work, grade) {
    Person.call(this, name, work);//继承属性
    this.grade = grade;
  }
  let student = new Student ('ReSword', 'Student', 'Junior');
  console.log(student.work);
  console.log(student.getName());
</script>
</html>

再来看class通过extends关键字的继承

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  class Person {
    constructor (name, work) {
      this.name = name;
      this.work = work;
    }
    getName () {
      return this.name;
    }
  }
  class Student extends Person {
    constructor (name, work, grade) {
      super(name, work);
      this.grade = grade;
    }
  }
  let student = new Student('ReSword', 'Student', 'Junior');
  console.log(student.work);
  console.log(student.getName());
</script>
</html>

注意点:

1,

等同于

2,必须要在super之后才能使用this,这是因为子类的创建是基于父类的,只有super方法才能调用父类实例

3,父类的静态方法也会被子类所继承

上面只是父类的属性调用,下面是讲父类的方法调用:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
  class Person {
    constructor (name, work) {
      this.name = name;
      this.work = work;
    }
    getName () {
      return `This is father's function ${this.name}`;
    }
  }
  class Student extends Person {
    constructor (name, work, grade) {
      super(name, work);
      this.grade = grade;
    }
    getName () {
      console.log(super.getName());
      return `This is son's function ${this.name}`;
    }
  }
  let student = new Student('ReSword', 'Student', 'Junior');
  console.log(student.work);
  console.log(student.getName());
</script>
</html>

注意点:

如果直接在子类中写和父类相同名字函数,那么其实际上只会执行子类的函数,

如果想要执行父类的函数,请使用super

### ES6 类的继承用法 在 ES6 中,`class` 关键字被正式引入,简化了面向对象编程中的类定义继承机制。通过 `extends` `super` 关键字可以轻松实现子类对父类的功能扩展。 #### 定义基类 (Parent Class) ```javascript class Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} makes a noise.`); } } ``` 此段代码展示了如何创建一个名为 `Animal` 的基础类,其中包含了一个构造函数用于初始化实例属性以及一个方法来表示动物发声的行为[^1]。 #### 创建派生类 (Child Class) 为了从已有类继承特性并添加新功能,可以通过指定另一个类作为参数传递给 `extends` 来完成: ```javascript class Dog extends Animal { constructor(name, breed) { super(name); // 调用父类构造器 this.breed = breed; // 添加额外属性 } bark() { // 新增特有行为 console.log(`Woof! I'm ${this.name}, a ${this.breed}.`); } speak() { // 重写父类的方法 return this.bark(); } } ``` 这里展示的是基于之前定义好的 `Animal` 基础之上构建出来的更具体的 `Dog` 子类。它不仅能够访问来自父级的所有公共成员变量与方法,还可以覆盖某些特定于自身的逻辑实现。 当实例化这些类时,可以看到完整的继承链效果: ```javascript const myPet = new Dog('Buddy', 'Golden Retriever'); myPet.speak(); // 输出: Woof! I'm Buddy, a Golden Retriever. ``` 上述例子说明了 ES6 如何利用简洁明了的方式处理复杂的多层继承关系,并且保持良好的可读性维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值