JavaScript 函数构造器与类构造器

469 阅读4分钟

在阐述构造器时,要先明确一下实例是什么?

实例是一个具体的对象,它是通过构造器、函数构造器或类构造器创建的。实例通常具有自己的属性和方法,也可以访问其构造器函数原型对象上定义的方法。

构造器

构造器(constructor)是一种特殊的函数,用于创建实例,构造器通常以大写字母开头,这样可以与普通函数区分开来。

语法规则:

new Constructor[(arguments)]

上面语句中 Constructor 就是我们常说的「构造器」,使用 new 关键字声明实例:

obj = new Constructor;
obj = new Constructor();
obj = new Constructor(arg1,arg2…)

构造器: 创建和初始化「对象」的一般性方法,需要使用 new 运算符让构造器产生实例。

在面向对象编程的语言中,有两种常见的构造器实现方式「函数构造器」和「类构造器」,下面我们来分析下这两种方法的概念和使用方法。

函数构造器: 函数构造器是使用函数来模拟类的概念。它使用构造器函数来创建实例,可以通过在构造器函数的原型对象上定义方法,来为实例添加属性和方法。

类构造器: 类构造器是 ES6 中新增的语法,它提供了一种更加直观和易读的方式来定义类。类构造器使用 class 关键字来定义类,可以使用 extends 关键字和 super 函数来实现继承。「类构造器本质也是一种函数,只是声明方式不一样。」

声明构造器

在使用 new 运算从「构造器」创建对象时,构造器既可以是一般函数,也可以是从 ES6 开始支持的类,这个类呢,也是一种声明构造器的方式,所以,声明一个类,也就是声明一个构造器函数。

//最简单的类声明
class MyObject {}
//构造函数声明风格
function MyObject() {}
//变量声明风格
const MyObject = new Function;

上面三种声明是等价的。

构造过程

将一般函数用作构造器时,函数体就是构造过程本身。

function MyObject() {
  console.log('构造过程...')
}

将一般函数作用构造器时,函数体就是构造过程本身。在使用 class 关键字时,该构造过程就被独立出来并用特定的方法名称来声明,就是「constructor」


class MyObject{
    constructor(){
        console.log('构造过程...')
    }
}

这样构造过程就声明完成了。

声明属性

如果我们用函数作为构造器时,需要通过原型来声明实例的属性。

function MyObject() {
    console.log('构造过程...')
}
//声明属性
MyObject.prototype.aName = 'value';
MyObject.prototype.aMethod = function(){
    //方法内容...
};

如果我们用 class 来声明呢,这些声明都可以采用特定的关键字或语法来声明:

class MyObject{
    get aName(){
        //声明读方法...
    }
    set aName(value){
        //声明写方法...
    }
    //声明方法
    aMethod() {
        //方法内容...
    }
}

通过特定的关键字或者语法来声明不同含义的属性和方法。

父类构造方法

我们用函数构造器来创建类,然后我们希望从子类的构造函数中来调用父类的构造函数,我们可以使用 call() 或 apply() 方法,将 this 指向父类实例。

function MyObject(name) {
  this.name = name;
}

function MyObjectEx(name, x) {
  MyObject.call(this, name);
  this.x = x;
}

我们在使用 this 关键字之前 ,需要先显示地调用 super() 以便在当前构造方法中获得 this 实例。

class MyObjectEx extends MyObject{
    constructor(){
        super();//必须在引用 this 之前调用
        this.x = 100
    }
}

通过 super() 可以在当前构造方法中获得 this 实例。

父类方法

在函数声明的语法中,我们想调用父类声明的方法时,需要在父类的原型中添加这个方法,子类就可以通过原型继承过去。

function MyObject(name) {
  this.name = name;
}
MyObject.prototype.aMethod = function() {
  console.log('Hello, my name is ' + this.name);
};

在类声明的语法中,可以直接使用 super.*** 来调用。

class MyObjectEx extends MyObject{
    foo(){
        super.aMethod()
    }
}

在调用时,也会隐式的传入当前 this 的引用,与在构造器中使用 super() 是一样的。

静态成员

访问类静态成员的时候不需要创建对象实例,因为它是类的自有成员。并且如果它是方法的静态方法和属性存取方法,那也可以使用 super 。


题图授权基于 www.pixabay.com 相关协议

内容来源于《JavaScript 语言精髓与编程实战》,部分内容来源于 ChatGPT。

如果您对本篇文章中提到的问题有任何疑问或想法,请在评论区留言,我将尽力回复。

微信公众号「小道研究」,获取更多关于前端技术的深入分析和实践经验。