JavaScript ES6 Class 类详解:语法、继承与注意事项

作者:青柠时间:2026-10-30 17:11:20浏览:129

本文深入解析 JavaScript ES6 中的 Class 类机制。文章指出 ES6 的 class 语法仅是原型链的语法糖,重点讲解了类声明与类表达式的区别、constructor 构造函数的作用、变量提升的限制,以及使用 extends 和 super 实现继承时的关键注意事项,帮助开发者正确理解和使用面向对象编程特性。

前言:JavaScript 中类的本质

前言

在 JavaScript 中,类并非必需的设计模式,而是一种可选方案。由于 JavaScript 是基于 [[Prototype]] 的语言,强行实现类机制往往显得不够自然。

这种不协调感不仅源于语法层面,尽管语法确实是重要因素。JavaScript 中存在诸多语法缺陷,例如繁琐且杂乱的 [[Prototype]] 引用、调用原型链上层同名函数时需要显式处理伪多态,以及容易引发误解的 [[.constructor]] 机制。

此外,类设计还面临更深层的问题。在传统面向类的语言中,父类与子类、子类与实例之间存在复制操作,但在 [[Prototype]] 机制中并不存在这种复制行为。

对象关联代码和行为委托直接利用 [[Prototype]] 而非将其隐藏,从简洁性对比来看,类机制并不完全适用于 JavaScript。

ES6 Class 基础语法

ES6 中 Class 的使用

JavaScript 的传统做法是:生成对象实例时,需先定义构造函数,再通过 new 关键字完成实例化。


function StdInfo(){
  this.name = "job";      
  this.age = 30;      
}

StdInfo.prototype.getNames = function (){
  console.log("name:"+this.name);        
}
//得到一个学员信息对象
var p = new StdInfo()

JavaScript 中只有对象,没有类。它是一门基于原型的语言,原型对象作为新对象的模板,将其自身属性共享给新对象。这种写法与传统面向对象语言差异巨大,常令新手感到困惑。

定义类

ES6 引入了类(Class)作为对象的模板。通过 class 关键字可以定义一个类:


//定义类
class StdInfo {
  constructor(){
    this.name = "job";      
    this.age = 30;   
  }
  //定义在类中的方法不需要添加function
  getNames(){
    console.log("name:"+this.name);   
  }
}
//使用new的方式得到一个实例对象
var p = new StdInfo();

上述写法更加清晰,贴近面向对象编程的语法风格,易于理解。

定义的类本质上只是语法糖,旨在提供更简洁明了的语法来创建对象及处理继承关系。


//定义类
class StdInfo {
  //...
}
console.log(typeof StdInfo); //function

console.log(StdInfo === StdInfo.prototype.constructor); //true

从测试可以看出,类的类型实际上是一个函数,属于一种“特殊函数”,指向构造函数。

函数的定义方式包括函数声明和函数表达式,类的定义方式同样分为两种:类声明和类表达式。

类声明与构造函数

类声明

类声明是使用 class 关键字定义类的一种方式,后接类名及一对大括号。将需要定义的方法放入大括号中。


//定义类,可以省略constructor
class StdInfo {
  getNames(){
    console.log("name:"+this.name);
  }
}
// -------------------------------------
//定义类,加上constructor
class StdInfo {
  //使用new定义实例对象时,自动调用这个函数,传入参数
  constructor(name,age){
    this.name = name;      
    this.age = age;   
  }
  
  getNames(){
    console.log("name:"+this.name);   
  }
}
//定义实例对象时,传入参数
var p = new StdInfo("job",30)

constructor 是默认方法,在使用 new 定义实例对象时自动执行。该函数接收传入的参数,执行完毕后自动返回实例对象。

一个类中只能包含一个 constructor 函数,若定义多个则会报错。

constructor 中的 this 指向新创建的实例对象,可利用 this 为新实例扩展属性。

若在定义实例对象时无需进行初始化操作,可不显式编写 constructor 函数。若未显式定义,系统会默认添加一个空的 constructor(){}。

类表达式与变量提升

类表达式

类表达式是定义类的另一种形式,类似于函数表达式,即将一个函数作为值赋给变量。可将定义的类赋值给变量,此时变量名即为类名。class 关键字后的类名可有可无;若存在,则仅在类内部可用。

定义类 class 后面有类名:


const People = class StdInfo {
  constructor(){
    console.log(StdInfo); //可以打印出值,是一个函数
  }
}

new People();
new StdInfo(); //报错,StdInfo is not defined;

定义类 class 后面没有类名:


const People = class {
  constructor(){

  }
}

new People();

立即执行的类:


const p = new class {
  constructor(name,age){
    console.log(name,age);
  }
}("job",30)

立即执行的类需在类前加上 new。p 为类的实例对象。

不存在变量提升

定义类不存在变量提升,必须遵循先定义后使用的原则,这与函数声明不同。


//-----函数声明-------
//定义前可以先使用,因为函数声明提升的缘故,调用合法。
func();
function func(){}

//-----定义类---------------
new StdInfo(); //报错,StdInfo is not defined
class StdInfo{}

使用 extends 实现继承

EXTENDS 继承

使用 extends 关键字实现类之间的继承。相比 ES5 中的继承方式,这更为便捷。


//定义类父类
class Parent {
  constructor(name,age){
    this.name = name;
    this.age = age;
  }

  speakSometing(){
    console.log("I can speek chinese");
  }
}
//定义子类,继承父类
class Child extends Parent {
  coding(){
    console.log("coding javascript");
  }
}

var c = new Child();

//可以调用父类的方法
c.speakSometing(); // I can speek chinese

通过继承方式,子类便拥有了父类的方法。

如果子类中包含 constructor 构造函数,则必须调用 super。


//定义类父类
class Parent {
  constructor(name,age){
    this.name = name;
    this.age = age;
  }

  speakSometing(){
    console.log("I can speek chinese");
  }
}
//定义子类,继承父类
class Child extends Parent {
  constructor(name,age){
    //不调super(),则会报错 this is not defined

    //必须调用super
    super(name,age);
  }

  coding(){
    console.log("coding javascript");
  }
}

var c = new Child("job",30);

//可以调用父类的方法
c.speakSometing(); // I can speek chinese

子类必须在 constructor 方法中调用 super 方法,否则新建实例时会报错(this is not defined)。原因是子类没有自己的 this 对象,而是继承父类的 this 对象并对其进行加工。若不调用 super 方法,子类将无法获得 this 对象。

总结

以上是对 ES6 中类的简单总结与学习,希望本文内容能对大家的编程工作有所帮助。如有疑问欢迎留言交流,感谢支持。

作者最新文章