首先,我建议你看一下this playlist 的主角本人(Crockford)。它可能很老,但它确实很好地解释了 JavaScript“逻辑”,您的问题在第三个视频中得到了特别解答。
我将通过描述在其他传统的面向对象编程语言中如何描述对象来开始回答这个问题,因为我还想针对您在问题开头发布的 Crockford 评论。
为了理解构造函数,你首先必须对对象有一个很好的理解。在传统的 OOP 语言中,对象是描述对象状态的变量(称为属性或字段)以及描述其行为的函数(称为方法)的集合。在那些(非 JavaScript)语言中,这些对象的“蓝图”称为类。
所以,如果我在 Java 中创建一个 Human 类,一个非常简单的描述将如下所示:
class Human {
String name;
int weight; // kg
int height; // cm
void eat(int foodWeight) {
this.weight += foodWeight;
}
Human(int weight, int height, int name) {
this.weight = weight;
this.height = height;
this.name = name;
}
}
然后,我将使用上面的“蓝图”创建一个 对象,如下所示:
Human Joe = new Human(90, 180, "Joe");
现在,我们说Joe 是 Human 的一个实例,其体重为 90 公斤,身高为 180 厘米。
在上面的类中,您注意到我有一个函数Human(),用于创建对象并在创建对象时定义它的状态。这基本上就是构造函数所做的。
那么 JavaScript 有什么不同呢?
为了在创建时吸引大众(正如您将在我发布的视频系列中听到的那样),JavaScript 结合了一些类似 Java 的语法。根据 Crockford 的说法,这样做的目的是让程序员认为,因为他们已经知道/学习了一些 Java,所以他们可以只学习一些新命令,然后继续使用 JavaScript 编程,而实际上,两者之间的差异两者的相似之处远远超过了它们的相似之处。
在 JavaScript 中,为了创建一个看起来像 Java 类的对象,您可以使用如下的函数语法:
var Human = function(name, height, weight) {
this.name = name;
this.height = height;
this.weight = weight;
this.eat = function(foodWeight) {
this.weight += foodWeight;
};
};
然后,如果您想像我们上面所做的那样定义Joe,您可以执行以下操作:
var Joe = new Human("Joe", 180, 90);
您可以看到所示的 Java 和 JavaScript 语法之间的相似之处。因此,回答您的第一个问题:JavaScript 构造函数是在使用 new 调用时创建并返回由 this 指向的隐式创建对象的函数。
那么原型从何而来?好吧,在 JavaScript 中,函数本身也是 JS 对象,它们有一个名为 prototype 的属性。所以,我们上面创建的Human()构造函数有一个属性叫prototype,这个属性指的是一个属性和方法都被Joe继承的对象,以及Human的所有其他实例,而这个对象可以扩展以创建将由所有这些实例继承的属性。
例如,Function.prototype 中的方法之一就是著名的toString 方法。你可以定义
Human.prototype.toString = function() {
return this.name + " is " + this.height + " cm tall and weighs " + this.weight + " kg";
}
然后,如果您调用Joe.toString() 或当您执行类似alert(Joe) 之类的自动调用toString() 时,返回的值将是“Joe 身高 190 厘米,体重 80 公斤”。
关于 OOP 和 JavaScript 的更多细节可以在您的问题的上下文中介绍,但我认为我的回答已经足够长了!我希望这能回答你的问题。