Basic syntax of the class keyword
ECMAScript 6 introduced the class
keyword, making object-oriented programming in JavaScript clearer and more readable. Although class
is essentially syntactic sugar over prototype-based inheritance, it provides a syntax closer to traditional object-oriented languages. Below is a detailed breakdown of its syntax features, method definitions, inheritance mechanisms, and related considerations.
Basic Class Definition
The class
keyword is used to define a class, with the class name typically following PascalCase naming conventions. Class declarations are not hoisted and must be defined before use.
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
}
const john = new Person('John');
john.sayHello(); // Output: Hello, my name is John
The constructor
method in the class body is the default constructor, automatically called when an object instance is created using the new
command. A class must have a constructor
method; if not explicitly defined, the JavaScript engine will add an empty constructor
by default.
Instance Methods and Static Methods
Methods defined in a class are instance methods by default and must be called through an instance. The static
keyword is used to define static methods, which are called directly on the class.
class MathUtils {
static square(x) {
return x * x;
}
cube(x) {
return x * x * x;
}
}
console.log(MathUtils.square(3)); // 9
const math = new MathUtils();
console.log(math.cube(3)); // 27
In static methods, this
refers to the class itself rather than an instance. Static methods are often used to implement utility functions or factory methods.
Property Definition Methods
In ES6 classes, instance properties can be defined directly in the constructor
or at the top level of the class using assignment statements. Static properties must be defined outside the class using the class name.
class Rectangle {
// New instance property syntax
height = 0;
constructor(width) {
this.width = width;
}
get area() {
return this.width * this.height;
}
}
// Static property
Rectangle.version = '1.0';
const rect = new Rectangle(10);
rect.height = 5;
console.log(rect.area); // 50
console.log(Rectangle.version); // '1.0'
Getters and Setters
The get
and set
keywords can be used to define getter and setter functions for a property, intercepting its access and assignment behavior.
class Temperature {
constructor(celsius) {
this.celsius = celsius;
}
get fahrenheit() {
return this.celsius * 1.8 + 32;
}
set fahrenheit(value) {
this.celsius = (value - 32) / 1.8;
}
}
const temp = new Temperature(25);
console.log(temp.fahrenheit); // 77
temp.fahrenheit = 86;
console.log(temp.celsius); // 30
Class Inheritance
The extends
keyword is used to implement inheritance. Subclasses can call the parent class's constructor and methods using the super
keyword.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // Call the parent class constructor
this.breed = breed;
}
speak() {
super.speak(); // Call the parent class method
console.log(`${this.name} barks.`);
}
}
const dog = new Dog('Rex', 'Labrador');
dog.speak();
// Output:
// Rex makes a noise.
// Rex barks.
Subclasses must call the super
method in their constructor
; otherwise, an error will occur when creating an instance. This is because the subclass's this
object must first be shaped by the parent class's constructor.
Private Properties and Methods
ES2022 officially added private properties and methods to the standard, defined by prefixing the property or method name with #
.
class Counter {
#count = 0; // Private property
#increment() { // Private method
this.#count++;
}
tick() {
this.#increment();
console.log(this.#count);
}
}
const counter = new Counter();
counter.tick(); // 1
counter.tick(); // 2
console.log(counter.#count); // Error: Private field '#count' must be declared in an enclosing class
Class Considerations
- Classes default to strict mode internally.
- Classes are not hoisted.
- Class methods are non-enumerable.
- All instances of a class share the same prototype object.
- The
new.target
property can be used to determine how the constructor was called.
class Shape {
constructor() {
if (new.target === Shape) {
throw new Error('This class cannot be instantiated');
}
}
}
class Rectangle extends Shape {}
const shape = new Shape(); // Error
const rect = new Rectangle(); // Works
Class Expressions
Like functions, classes can also be defined using expressions. The class name in a class expression is only valid inside the class. If omitted, it becomes an anonymous class.
const MyClass = class Me {
getClassName() {
return Me.name;
}
};
const inst = new MyClass();
console.log(inst.getClassName()); // "Me"
console.log(Me); // Error: Me is not defined
Mixin Pattern Implementation
Simple Mixin patterns can be implemented using class inheritance, a technique for combining the functionality of multiple classes into one.
const Serializable = Base => class extends Base {
serialize() {
return JSON.stringify(this);
}
};
const Loggable = Base => class extends Base {
log() {
console.log(this.toString());
}
};
class Person {
constructor(name) {
this.name = name;
}
toString() {
return `Person: ${this.name}`;
}
}
const EnhancedPerson = Serializable(Loggable(Person));
const person = new EnhancedPerson('Alice');
person.log(); // "Person: Alice"
console.log(person.serialize()); // "{"name":"Alice"}"
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:Promise的微任务队列特性
下一篇:constructor方法