在阐述构造器时,要先明确一下实例是什么?
实例是一个具体的对象,它是通过构造器、函数构造器或类构造器创建的。实例通常具有自己的属性和方法,也可以访问其构造器函数原型对象上定义的方法。
构造器
构造器(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。
如果您对本篇文章中提到的问题有任何疑问或想法,请在评论区留言,我将尽力回复。
微信公众号「小道研究」,获取更多关于前端技术的深入分析和实践经验。