一、前言
在 JavaScript 中,constructor 是一个重要概念,同时也是一个关键词。初学者可能并不理解 constructor 的具体作用和应用场景,本文将围绕 constructor 展开,探究其作用和应用场景。
二、constructor 的定义
constructor 是一个函数,用于创建对象的实例。每个 JavaScript 对象都有一个 constructor 属性,该属性指向创建该对象的构造函数。constructor 属性返回的是一个引用,指向用于创建该对象的函数。
例如:
```javascript
function Person(name) {
this.name = name;
}
var person = new Person("张三");
console.log(person.constructor); // Person(name)
```
在上面的代码中,当我们创建一个 Person 对象实例时,它的 constructor 属性就被设置为 Person,因为 Person 是用于创建该对象的构造函数。我们可以通过 console.log(person.constructor) 输出构造函数名,以便验证是否是符合预期的。
三、constructor 的应用场景
constructor 主要用于两个方面的功能:对象的类型检测和实例对象的创建。
1. 对象的类型检测
常常需要在程序中检查某个对象是否是特定类型的实例。此时,constructor 就可以派上用场了。constructor 属性可以用于判断一个对象是不是指定类型的实例。
例如:
```javascript
function Person(name) {
this.name = name;
}
var person = new Person("张三");
console.log(person.constructor === Person); // true
```
在上面的代码中,我们通过 person.constructor === Person 来判断 person 是否是 Person 的实例。
另外,对于基本数据类型来说,只要使用 typeof 运算符即可判断其类型。
例如:
```javascript
console.log(typeof 3); // "number"
console.log(typeof "abc"); // "string"
console.log(typeof true); // "boolean"
```
2. 实例对象的创建
使用 constructor 创建实例对象的方法和使用 new 关键字创建实例对象的方法很相似。我们可以通过下面的代码来验证这一点。
```javascript
function Person(name) {
this.name = name;
}
var person1 = new Person("张三");
var person2 = new person1.constructor("李四");
console.log(person2.name); // "李四"
```
在上面的代码中,我们先创建了一个 Person 对象实例 person1,然后通过 person1.constructor 创建了另一个 Person 对象实例 person2。
四、constructor 与 prototype
constructor 属性和 prototype 属性密不可分,它们共同构成了 JavaScript 中的对象模型。
constructor 属性指向的是创建该对象的构造函数。当我们在创建自定义构造函数时,该构造函数的 prototype 属性就被设置为一个空对象。我们可以在该对象的属性中添加属性和方法,这样在使用该构造函数创建的实例对象就可以访问这些属性和方法了。
例如:
```javascript
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log("Hello " + this.name);
}
var person = new Person("张三");
person.sayHello(); // "Hello 张三"
```
在上面的代码中,我们在 Person 的 prototype 属性对象中添加了一个名为 sayHello 的方法。当我们创建一个 Person 对象实例时,就可以通过实例对象的 sayHello 方法进行调用。这就是 constructor 和 prototype 配合使用的一个常见方式。
实际上,JavaScript 使用基于原型的继承机制,而 constructor 和 prototype 的作用就是为了更加方便的实现继承。
例如:
```javascript
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log("Hello " + this.name);
}
function Student(name, grade) {
Person.call(this, name); // 调用父类构造函数
this.grade = grade;
}
Student.prototype = Object.create(Person.prototype); // 继承自 Person.prototype
Student.prototype.constructor = Student; // 修复constructor属性
Student.prototype.study = function() {
console.log(this.name + "正在学习,他的成绩是" + this.grade + "。");
}
var student = new Student("李四", 80);
student.sayHello(); // "Hello 李四"
student.study(); // "李四正在学习,他的成绩是80。"
console.log(student instanceof Student); // true
console.log(student instanceof Person); // true
```
在上面的代码中,我们创建了两个构造函数:Person 和 Student。Person 就是一个简单的对象构造函数;Student 则继承自 Person,并通过添加 study 方法来增强它的功能。
在创建 Student 对象实例时,我们通过调用父类构造函数 Person.call(this, name) 来初始化父类属性。我们还指定了 Student.prototype = Object.create(Person.prototype) 来确保 Student 对象实例继承了 Person 的所有属性和方法。这样可以保证 Student 对象实例从 Person 对象实例那里继承而来的所有方法都可以顺利访问。
由于在上述继承过程中 Student.prototype.constructor 被 Person.constructor 覆盖,因此需要显式地将其指回 Student,以保证 constructor 属性自身的正确性。
整个过程可以一句话概括:通过修改 constructor 属性,让子类构造函数的 prototype 属性指向父类构造函数的 prototype 属性。这样,子类构造函数就可以在继承父类方法的同时,添加自己特有的方法。
五、小结
本文主要探讨了 JavaScript 中 constructor 的作用和应用场景。通过对 constructor 属性和 prototype 属性的介绍和应用,帮助读者更好地理解 JavaScript 中的对象模型和继承机制。