The constructor method translates this sentence into English.
Basic Concepts of the constructor Method
The constructor
method is the constructor function of a class in ECMAScript 6, used to create and initialize objects created by the class. When a class is instantiated using the new
keyword, the constructor
method is automatically called. This method is special in a class—it is neither a static method nor an instance method.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const person1 = new Person('Zhang San', 25);
console.log(person1.name); // Output: Zhang San
Characteristics of the constructor Method
The constructor
method has several important features to note:
- Each class can have only one
constructor
method; otherwise, aSyntaxError
will be thrown. - If no
constructor
method is explicitly defined, JavaScript provides a default one. - The
constructor
method returns the instance object (this
) by default but can return other objects.
class Animal {
// No explicit constructor defined
}
const animal = new Animal();
// JavaScript automatically adds the following constructor:
// constructor() {}
Parameters of the constructor Method
The constructor
method can accept any number of parameters, which are passed when the class is instantiated:
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
get area() {
return this.height * this.width;
}
}
const rect = new Rectangle(10, 20);
console.log(rect.area); // Output: 200
super Call in constructor
In an inherited class, the constructor
method must call super()
before using the this
keyword:
class Animal {
constructor(name) {
this.name = name;
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // Must call super first
this.breed = breed;
}
}
const myDog = new Dog('Wang Cai', 'Golden Retriever');
console.log(myDog.name); // Output: Wang Cai
Special Cases of constructor Return Values
Although constructor
typically does not explicitly return a value, if it returns an object, that object will replace the default created instance:
class Foo {
constructor() {
return { bar: 'baz' };
}
}
const foo = new Foo();
console.log(foo); // Output: { bar: 'baz' }
console.log(foo instanceof Foo); // Output: false
constructor vs. Prototype Methods
The constructor
method differs from other class methods in that it is not added to the class's prototype:
class Example {
constructor() {}
method() {}
}
console.log(Example.prototype.method); // Output: [Function: method]
console.log(Example.prototype.constructor); // Output: [class Example]
Default Implementation of constructor
When a class does not explicitly define a constructor
, the JavaScript engine automatically adds different default constructors based on the situation:
// Base class
class Base {}
// Equivalent to:
// class Base {
// constructor() {}
// }
// Derived class
class Derived extends Base {}
// Equivalent to:
// class Derived extends Base {
// constructor(...args) {
// super(...args);
// }
// }
Property Initialization in constructor
ES6 supports defining instance properties directly in the class, which can replace some initialization code in the constructor
:
class OldWay {
constructor() {
this.counter = 0;
}
}
class NewWay {
counter = 0; // Class fields proposal
}
const old = new OldWay();
const newWay = new NewWay();
console.log(old.counter, newWay.counter); // Output: 0 0
constructor and Private Fields
ES2022 introduced private fields, which must be declared before the constructor
and can only be accessed within the class:
class Counter {
#count = 0; // Private field
constructor(initialValue) {
if (initialValue !== undefined) {
this.#count = initialValue;
}
}
increment() {
this.#count++;
}
get value() {
return this.#count;
}
}
const counter = new Counter(5);
counter.increment();
console.log(counter.value); // Output: 6
console.log(counter.#count); // Error: Private field '#count' must be declared in an enclosing class
constructor and Static Initialization Blocks
ES2022 introduced static initialization blocks for complex static property initialization:
class MyClass {
static x;
static y;
static {
// Can access private static fields
try {
const result = someComplexInitialization();
this.x = result.x;
this.y = result.y;
} catch {
this.x = 0;
this.y = 0;
}
}
constructor() {
// Instance initialization
}
}
Performance Considerations for constructor
The performance of the constructor
method affects object creation speed, especially in scenarios where instances are frequently created:
class Optimized {
constructor(a, b) {
this.a = a;
this.b = b;
// Avoid complex calculations in the constructor
}
}
class Unoptimized {
constructor(a, b) {
this.a = a;
this.b = b;
this.c = this.computeSomething(); // Complex calculations in the constructor impact performance
}
computeSomething() {
let result = 0;
for (let i = 0; i < 1000000; i++) {
result += Math.random();
}
return result;
}
}
constructor and Inheritance Chains
In complex inheritance relationships, the calling order of constructor
follows the prototype chain:
class A {
constructor() {
console.log('A constructor');
}
}
class B extends A {
constructor() {
super();
console.log('B constructor');
}
}
class C extends B {
constructor() {
super();
console.log('C constructor');
}
}
const c = new C();
// Output:
// A constructor
// B constructor
// C constructor
constructor and new.target
The new.target
meta-property can be used in the constructor
to detect how the class was called:
class Shape {
constructor() {
if (new.target === Shape) {
throw new Error('Shape class cannot be instantiated directly');
}
}
}
class Circle extends Shape {}
// new Shape(); // Error: Shape class cannot be instantiated directly
new Circle(); // Works
constructor and Asynchronous Initialization
Although uncommon, the constructor
can contain asynchronous operations, but note the case of returning a Promise:
class AsyncExample {
constructor() {
return (async () => {
await someAsyncOperation();
return this; // Must return this
})();
}
}
// Usage requires await
(async () => {
const instance = await new AsyncExample();
})();
constructor and Proxies
The constructor
call can be intercepted using a Proxy:
class Base {
constructor(value) {
this.value = value;
}
}
const Handler = {
construct(target, args) {
console.log(`Creating instance with args: ${args}`);
return new target(...args);
}
};
const ProxiedClass = new Proxy(Base, Handler);
const instance = new ProxiedClass(42); // Output: Creating instance with args: 42
constructor and Decorators
Decorators can be used to modify the behavior of a class's constructor
:
function logConstructor(target) {
const original = target.prototype.constructor;
target.prototype.constructor = function(...args) {
console.log(`Creating instance with args: ${args}`);
return original.apply(this, args);
};
return target;
}
@logConstructor
class MyClass {
constructor(a, b) {
this.a = a;
this.b = b;
}
}
const obj = new MyClass(1, 2); // Output: Creating instance with args: 1,2
constructor and Class Expressions
The behavior of constructor
in class expressions is consistent with that in class declarations:
const Person = class {
constructor(name) {
this.name = name;
}
};
const person = new Person('Li Si');
console.log(person.name); // Output: Li Si
constructor and Generator Methods
Although the constructor
itself cannot be a generator function, it can call generator methods:
class Sequence {
constructor(start, end) {
this.start = start;
this.end = end;
}
*[Symbol.iterator]() {
for (let i = this.start; i <= this.end; i++) {
yield i;
}
}
}
const seq = new Sequence(1, 5);
console.log([...seq]); // Output: [1, 2, 3, 4, 5]
constructor and Symbol.species
Symbol.species
can override the constructor
, useful for derived collection objects:
class MyArray extends Array {
static get [Symbol.species]() {
return Array; // Overrides the default constructor
}
constructor(...args) {
super(...args);
}
}
const myArray = new MyArray(1, 2, 3);
const mapped = myArray.map(x => x * 2);
console.log(mapped instanceof MyArray); // Output: false
console.log(mapped instanceof Array); // Output: true
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:class关键字基本语法
下一篇:静态方法和属性