我正在参加「掘金·启航计划」!
当您在学习 JavaScript 时,可能会混淆构造函数
和原型
之间的区别。通常,它们可以互换使用来描述相似的概念,但它们实际上是用于不同目的的不同事物。
在这篇文章中,我们将揭开这两个术语的神秘面纱并解释它们之间的区别。
简单的区分
那么构造函数和原型有什么区别呢?
一个简单的区分是,构造函数是一个用于创建对象的函数,而原型是一个包含属性和方法的对象,这些属性和方法由从构造函数创建的对象继承。
我们来看一个例子:
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}.`);
}
const person = new Person('John');
person.sayHello(); // Hello, my name is John.
在上面的示例中,我们有一个构造函数,它接受一个name
参数并将其分配给name
对象的属性。我们还有一个名为 sayHello
的原型方法,它向控制台打印一条消息。
当我们Person
使用构造函数创建一个新对象时,我们可以调用它的sayHello
方法,它会打印带有我们传递给构造函数的名称的消息。
person
对象可以使用该方法sayHello
,因为它继承自 Person
构造函数的原型。
系统的区分
构造函数概述
构造函数是用于创建对象的函数。当您使用关键字调用构造函数时new
,它将创建一个新对象并返回它。
如果您有面向对象编程(OOP)的 背景,将构造函数与类进行比较是最简单的。就像在其他语言中一样,构造函数允许您创建新对象并定义它们的属性和方法。
例如,让我们比较一个简单的 Java 类,以及我们如何使用构造函数在 JavaScript 中实现相同的功能:
Java
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public void sayHello() {
System.out.println("Hello, my name is " + this.name);
}
}
Person person = new Person("John");
person.sayHello(); // Hello, my name is John
JavaScript
在 JavaScript 中,我们可以创建Person
具有相同属性和方法的构造函数:
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}.`);
}
const person = new Person('John');
person.sayHello(); // Hello, my name is John.
如您所见,两者非常相似。主要区别在于,在 JavaScript 中,我们使用prototype
将方法添加到构造函数中,而在 Java 中,我们只需将它们添加到类中。
事实上,ES6 附带的新类语法是语法糖,旨在使构造函数的使用更类似于其他 OOP 语言。
还要注意我们如何this
在 JavaScript 构造函数中使用。this
指使用new
关键字时隐式创建的对象。
原型概述
现在让我们更详细地介绍一下原型,以及为什么我们使用它在创建的对象之间共享构造函数的属性和方法。
在 JavaScript 中,函数本身也是 JS 对象,它们有一个叫做原型的属性。
原型的目的是在从构造函数创建的对象之间共享属性和方法。
例如,在上面的 Person 构造函数中,我们向sayHello
原型添加了一个方法。这意味着从 Person 构造函数创建的每个对象都有一个sayHello
方法。
原型链
Prototype
以一种节省内存的方式在对象之间共享属性。如果我们向原型添加一个方法,则该方法的一个实例只存在于内存中,并且在从构造函数创建的所有对象之间共享。
如果我们将sayHello
方法直接添加到 Person 构造函数中,那么每个对象都将拥有该方法的自己的副本,从而占用更多内存。
这称为原型链,它是 JavaScript 语言的重要组成部分。
下面是原型链的工作原理: 当 JavaScript 在对象上查找属性时,它会首先检查该属性是否存在于对象本身上。如果没有找到,它会查看对象的原型,看属性是否存在。
如果不存在,它将查看原型的原型,依此类推,直到找到匹配项或到达原型链的末尾。
创建对象后修改原型
使用构造函数和原型的好处之一是我们可以在创建对象后向原型添加新的属性和方法。
例如,假设我们要向Person 构造函数添加一个getName
方法:
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}.`);
}
const person = new Person('John');
person.sayHello(); // Hello, my name is John
Person.prototype.getName = function() {
return this.name;
}
console.log(person.getName()); // John
如您所见,我们能够在创建对象getName
后将方法添加到原型person
中,并且仍然可以按预期工作。
结论
总之,JavaScript中构造函数和原型的主要区别在于构造函数用于创建对象,而原型用于在对象之间共享属性和方法。