ES5与ES6类机制深度对比:语法、继承与作用域差异
本文详细对比ES5与ES6中类的定义与调用方式。ES5依赖构造函数与原型链,而ES6引入class关键字作为语法糖。重点分析两者在实例化必须使用new、变量提升机制(函数作用域vs块作用域)、静态成员定义及继承原理(先创建子类实例vs父类实例)上的核心差异,帮助开发者深入理解JavaScript面向对象编程的演进。
类定义与调用的区别
在 ES5 中,类的定义主要依赖构造函数配合原型链方式实现;而 ES6 引入了 class 关键字,赋予代码正式类的语义能力。尽管 class 是 ECMAScript 中新的基础性语法糖结构,表面上支持正式的面向对象编程,但其底层机制依然基于原型和构造函数。
使用 ES5 定义一个类并调用
function Person(name, age, job) {
this.name = "Totora";
this.age = 19;
this.job = "student";
this.sayName = function() {
console.log(this.name);
};
}
let person = new Person();
person.sayName();
使用 ES6 定义一个类并调用
ES6 提供了两种定义类的方式:类声明(class declaration)和类表达式(class expression)。
class Person {
constructor() {
this.name = "Totora";
this.age = 19;
this.job = "student";
}
sayName() {
console.log(this.name);
}
}
let person = new Person();
person.sayName();
//当我们使用typeof检测Person的类型时:
console.log(typeof Person); //function,它的本质仍然是函数
在调用类时,无论是 ES5 还是 ES6,都必须使用 new 操作符进行实例化,禁止直接执行调用。
两者的主要区别在于直接调用时的行为表现:
ES5 中直接调用构造函数不会报错,代码可正常执行,因为 ES5 中的构造函数与普通函数在行为上差异较小。
function Person(name, age, job) {
this.name = "Totora";
this.age = 19;
this.job = "student";
this.sayName = function() {
console.log(this.name);
};
}
let person = Person();
console.log(person); //undefined
ES6 中直接调用类会抛出错误,提示必须使用 new。
class Person {
constructor() {
this.name = "Totora";
this.age = 19;
this.job = "student";
}
sayName() {
console.log(this.name);
}
}
let person =Person();
console.log(person);
person.sayName(); //Class constructor Person cannot be invoked without 'new'
变量提升
通过对比测试可以发现,在 ES6 中使用 class 声明类时,如果在声明前尝试实例化会报错,这表明 ES6 的 class 不支持变量提升。
传统函数受函数作用域限制,而 class 定义的类受块级作用域(block scope)限制,这导致了暂时性死区(TDZ)的行为。
//变量提升
let person = new Person()
function Person(name, age, job) {
this.name = "Totora";
this.age = 19;
this.job = "student";
this.sayName = function() {
console.log(this.name);
};
}
person.sayName(); //Totora
let person = new Person();
class Person {
constructor() {
this.name = "Totora";
this.age = 19;
this.job = "student";
}
sayName() {
console.log(this.name);
}
}
person.sayName(); // Cannot access 'Person' before initialization
class中类的构成
一个完整的类可以包含构造函数、实例方法、getter(获取函数)、setter(设置函数)以及静态方法。值得注意的是,即使是一个空的类定义,在语法上也是有效的。
//空类定义
class Foo {}
//有构造函数的类
class Bar {
constructor() {}
}
//有获取函数的类
class Baz {
get myBaz() {}
}
//有静态方法的类
class Qux {
static myQux() {}
}
class中的静态方法
可以在类上定义静态方法,使用 static 关键字作为前缀。在静态成员内部,this 指向类本身而非实例。
与原型成员类似,每个类上静态成员的定义是唯一的。
使用 static 声明的静态属性和方法都可以被子类通过继承机制访问。
class Person {
constructor() {
//添加到this的所有内容都会存在于不同的实例上
this.locate = () => console.log('instance', this);
}
//定义在类的原型对象上
locate() {
console.log('prototype', this);
}
//定义在类本身上
static locate() {
console.log('class', this);
}
}
let p = new Person();
p.locate(); //instance Person { locate: [Function (anonymous)] }
Person.prototype.locate(); //prototype {}
Person.locate(); //class [class Person]
class Person {
static name() {
this.job(); //此处的this指向类
}
static job() {
console.log('Totora'); //不会出现在实例中
}
job() {
console.log('student');
}
}
Person.name(); //Totora
继承
ES5 中的继承实质是先创建子类的实例对象,再通过 Parent.apply(this) 将父类的方法绑定到 this 上,或者通过修改原型链来实现。
ES6 的继承机制不同,它实际上是先创建父类的实例对象 this,然后再使用子类的构造函数对 this 进行修改和增强。
在 ES6 中,类通过 extends 关键字可以继承任何拥有 [[Construct]] 方法和原型的对象。这不仅允许继承类,也允许继承普通的构造函数,从而保持了向后兼容性。
ES6 中派生类的方法可以通过 super 关键字引用父类的原型。该关键字只能在派生类中使用,且仅限于类的构造函数、实例方法和静态方法的内部。在构造函数中使用 super 可以调用父类构造函数。
//ES5中的继承
function parent(a,b) {
this.a = a;
this.b = b;
}
function child(c) {
this.c = c;
}
parent.call(child, 1, 2); //子级来继承父级
child.prototype = new parent(1, 2);
//ES6中的继承
class parent {
constructor(a, b) {
this.a = a;
this.b = b;
}
parentMethods() {
return this.a + this.b
}
}
class child extends parent {
constructor(a, b, c) {
super(a, b); //通过super调用父类
this.c = c;
}
childMethods() {
return this.c + ',' + super.parentMethods() //通过super实例化调用父类
}
}
const point = new child(1, 2, 3);
console.log(point.childMethods());
总结
到此这篇关于ES5和ES6中类区别的文章就介绍到这了,更多相关ES5和ES6类的区别内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
ES6模块化中js文件怎么用import和export交互
2026-11-05 17:00:48
JS读取本地文件时报错或无响应的常见原因
2026-11-05 16:32:31
let、const与var的区别:JavaScript变量声明最佳实践
2026-11-05 14:16:38
JS中直接定义静态二维数组的字面量写法
2026-11-05 14:16:08
JS 怎么查找字符串中所有匹配项的位置
2026-11-05 14:15:53
