JavaScript ES6 Class类详解:从基础语法到继承与私有成员
本文深入解析 JavaScript ES6 中的 Class 类机制,涵盖构造函数、getter/setter、静态成员及私有属性的定义与使用。重点讲解通过 extends 实现继承、super 关键字的作用,以及私有属性(#前缀)的访问限制与判断方法,帮助开发者掌握现代 JS 面向对象编程的核心概念。
Class类
ES6 引入了 Class(类)这一概念,作为对象的模板,其写法更贴近传统面向对象语言。通过 class 关键字定义类,本质上 ES6 的 class 只是语法糖,其核心功能在 ES5 中均可实现,主要优势在于使对象原型的写法更加清晰,符合面向对象编程的语法习惯。
初识class
在 ES5 中,通常通过构造函数来实现实例化。
<script>
// 定义人类
function People(name,age){
this.name = name
this.age = age
}
// 添加方法
People.prototype.say = function (){
console.log('hello world');
}
// 实例化方法
let person = new People('张三',18)
person.say()//hello world
console.log(person);//People {name: '张三', age: 18}
</script>ES6 class 方法实现
constructor() 是类的默认方法,使用 new 命令生成实例时自动调用。类必须包含 constructor() 方法,若未显式定义,系统将默认添加一个空的 constructor() 方法。
<script>
// class
class People {
// 构造方法 名字是固定格式不能修改
constructor(name,age){
this.name = name
this.age = age
}
// 方法必须使用该语法,不能使用 ES5 的对象完整形式
say(){
console.log('hello world');
}
}
// 实例化对象
let person = new People('张三',18)
person.say()//hello world
console.log(person);//People {name: '张三', age: 18}
</script>class中getter和setter设置
在 ES6 类内部,可以使用 get 和 set 关键字定义取值函数(getter)和存值函数(setter),从而拦截属性的读取与赋值行为。
<script>
class People {
get name(){
console.log('我是张三');
return '这是我的名字'//如果不写return,默认是undefined
}
set name(Name){//形参必须有
console.log('我的名字被修改了');
}
}
// 实例化对象
let p = new People()
// 只要读取 p 的实例化属性,就会执行 get 关键字函数里面代码,而且这个函数的返回值就是属性的一个值
console.log(p.name);
// 只要对 name 属性进行一个修改,如果有set关键字函数,就会执行该函数
p.name = 'f'
</script>
表达式方式书写
类可以通过表达式定义,与函数类似。需注意,类名仅在 Class 内部有效,指代当前类;在 Class 外部,只能通过定义该类的常量来引用。
<script>
const myClass = class Me {
getClass(){
return Me.name//返回类名
}
}
let c = new myClass()
console.log(c.getClass())//Me
Me.name//Me is not defined
// 如果类的内部没用到的话,可以省略Me,也就是可以写成下面的形式
const MyClass = class {};
</script>静态属性与静态方法
静态属性属于 Class 本身,即 Class.propName,而非定义在实例对象 this 上的属性。
实例对象的属性与构造函数的原型对象相通,实例对象只能继承构造函数原型中的属性和方法,二者属性不相通。
<script>
function People(){
}
// 函数属性和方法
People.name = '张三'
People.say = function(){
console.log('hello world');
}
// 原型对象属性和方法
People.prototype.age = 18
// 实例化对象
let p = new People()
console.log(People.name,People.say());
console.log(p.age);
console.log(p.name,p.say());
</script>
在 ES6 中,Class 内部仅支持静态方法,不支持静态属性。若要设置静态属性,需在实例属性前加上 static 关键字;静态方法同样需加 static 关键字,表示该方法不会被实例继承,而是直接通过类调用。
<script>
class People {
// 静态属性
static name = '张三'
static say(){
console.log('hello world');
}
}
let p = new People()
console.log(p.name);//undefined
console.log(People.name);//张三
</script>私有属性和私有方法
常见需求是定义私有属性和方法,即仅在类内部访问,外部不可见,这有助于代码封装。
ES6 正式为 class 添加了私有属性和方法,通过在属性或方法名前使用 # 符号表示。若不带 #,则被视为普通属性和方法。
<script>
class person {
// 私有属性
#name
constructor(name){
this.#name = name
}
// 私有方法
#sayName(){
return this.#name
}
result(){
console.log(this.#name);
}
}
let p = new person()
p.result = '张三'
console.log(p);//person {result: '张三', #sayName: ƒ, #name: undefined}
p.#name//报错
</script>判断类中私有属性是否存在时,可使用 in 运算符进行检测。
<script>
class A {
#foo = 0;
m() {
console.log(#foo in this); // true
console.log(#bar in this); // Private field '#bar' must be declared in an enclosing class(提示我们:私有字段“#bar”必须在封闭类中声明)
}
}
let a = new A()
a.m()
</script>class继承
在 ES5 中,通常通过构造函数实现继承。
另一种方式是通过原型链进行继承。若不熟悉原型链,可参考相关教程。
<script>
// 动物
function Animals(name,age){
this.name = name
this.age = age
}
Animals.prototype.call = function(){
console.log('我是动物');
}
// 狗
function Dog(name,age,color,gender){
// 改变this的指向,继承父类
Animals.call(this,name,age)
this.color = color
this.gender = gender
}
// 设置子类构造函数的原型
Dog.prototype = new Animals //此时子类的实例对象就会继承父类上面的方法
Dog.prototype.constructor = Dog
// 声明子类的方法
Dog.prototype.say = function(){
console.log('汪汪汪!!!');
}
// 子类对象进行实例化
const d = new Dog('小明',3,'棕色','雄')
console.log(d);
</script>
class类实现继承
class 可通过 extends 关键字实现继承,使子类继承父类的属性和方法。相比原型链继承,extends 的写法更为清晰便捷。
<script>
class Animals {
// 构造方法
constructor(name,age){
this.name = name
this.age = age
}
// 父类成员的属性
call(){
console.log('我是动物');
}
}
class Dog extends Animals {
// 构造方法
constructor(name,age,color,gender){
// 调用父类方法,需要用super(),super()就是父类的constructor()方法
super(name,age)
this.color = color
this.gender = gender
}
// 子类独有的方法
say(){
console.log('汪汪汪!!!');
}
// 当子类和父类重名时,优先调用的是子类的方法
call(){
console.log('我也是动物');
// 如果想调用父类方法,使用如下语句:super.父类方法()
super.call()
}
}
// 实例化子类对象
const d = new Dog('小明',3,'棕色','雄')
console.log(d);
d.call()
d.say()
</script>
super 关键字
代码中使用的 super 关键字用于调用父类的构造函数。子类继承父类的 constructor() 时必须包含 super(),否则报错。super 代表父类构造函数,但返回的是子类实例,即 super 内部的 this 指向子类实例。作为函数时,super() 仅能在子类的构造函数中使用,在其他地方使用会报错。
判断继承是否存在
Object.getPrototypeOf() 方法可从子类获取父类,因此可用于判断一个类是否继承自另一个类。
<script>
class people {}
class boy extends people {}
console.log(Object.getPrototypeOf(boy) === people);//true
</script>静态属性和方法继承
父类的静态属性和方法也能被子类继承,具体示例如下。
<script>
class people {
// 父类静态属性 属性为数值
static age = 18
// 父类静态属性 属性为对象
static h = {height:180}
// 父类静态方法
static say(){
console.log('hello world');
}
}
// 子类继承父类
class boy extends people {
constructor(){
// 调用父类的构造函数
super()
// boy类继承静态属性时,会采用浅拷贝,拷贝父类静态属性的值,因此people.age和boy.age是两个彼此独立的属性。
boy.age--
// 如果父类的静态属性的值是一个对象,那么子类的静态属性也会指向这个对象,因为浅拷贝只会拷贝对象的内存地址所以,子类修改这个对象的属性值,会影响到父类。
boy.h.height--
}
}
// 实例化子类
let b = new boy()
boy.say()
console.log(people.age);
console.log(boy.age);
console.log(boy.h.height);
console.log(people.h.height);
console.log(b);
</script>
私有属性和方法继承
私有属性和方法仅定义在所属 class 内部使用,因此子类会继承父类的所有属性和方法,除了私有属性和方法。若需让子类访问父类中的私有属性和方法,可通过父类定义的私有属性读写方法实现,子类即可通过这些方法读取私有属性。
<script>
class people {
#name = '张三'
// 定义用来读取私有属性和方法的函数
getName(){
return this.#name
}
}
class boy extends people {
constructor(){
// 调用父类的构造函数
super()
console.log(this.getName());//张三
}
}
let b = new boy()
</script>class显示原型与隐式原型关系
每个对象都有隐式原型 __proto__ 属性,指向对应构造函数的显示原型 prototype 属性。Class 作为构造函数的语法糖,同样具有 prototype 和 __proto__ 属性,因此存在两条继承链。此处仅作了解。
<script>
class people {}
class boy extends people{}
// 子类的__proto__属性,表示构造函数的继承,总是指向父类。
console.log(boy.__proto__ === people); // true
// 子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。
console.log(boy.prototype.__proto__ === people.prototype); // true
</script>到此这篇关于JavaScript Class类实例讲解的文章就介绍到这了,更多相关JS Class类内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
JavaScript入门书籍避坑:这些书不适合初学者
2026-11-05 16:31:15
JS使用Math.round实现保留两位小数的原理与代码
2026-11-05 15:35:55
JavaScript 原生 Date 对象怎么实现日期加减
2026-11-05 14:30:00
JavaScript函数定义的三种方式:声明、表达式与箭头函数
2026-11-05 13:50:55
JavaScript中escape、encodeURI和encodeURIComponent对空格的处理差异
2026-11-05 12:47:23
