JavaScript中函数和构造函数有什么区别?

22

这篇博客中,作者说以下函数是一个构造函数:

function Cat(name, color) {
  this.name = name;
  this.color = color;
}
Cat.prototype.age = 0;

var catC = new Cat("Fluffy", "White");

Cat 函数的实例具有名称和颜色属性。这是普通函数和 构造函数 之间唯一的区别吗?


1
更详细和准确的答案:如何检查Javascript函数是否为构造函数 - rosshjb
4个回答

54
一个构造函数是一个普通函数。不同的是使用new操作符会将函数中的上下文(this)设为新的实例,从而使其具有两个属性并返回该新实例。如果没有new操作符,上下文将是外部上下文(在松散模式下的全局作用域中为window,在严格模式下为undefined)。也就是说,如果省略了new
var catC = Cat("Fluffy", "White");

如果您未启用严格模式,则该函数“运行”,但会产生两个不同的结果:

  • catC 未定义,因为您的函数没有返回任何内容
  • namecolor 现在是外部作用域的属性

整个魔法都在new 运算符中:

执行代码 new foo(...) 时,会发生以下事情:

新对象将被创建,并从 foo.prototype 继承。

构造函数 foo 将使用指定的参数并将 this 绑定到新创建的对象来调用。new foo 等效于 new foo(),即如果未指定参数列表,则不带参数地调用 foo。

由构造函数返回的对象成为整个 new 表达式的结果。如果构造函数未显式返回对象,则使用在步骤 1 中创建的对象。(通常构造函数不返回值,但如果它们想要覆盖正常的对象创建过程,则可以选择这样做。)

当我说它是一个普通函数时,我忽略了一件事:开发人员的意图。通常情况下,您定义函数要么被称为构造函数(即使用 new),要么不是。在第一种情况下,您通常使用参数来初始化实例的字段(使用 this.name = ...),然后您经常跟随通过添加函数到原型(就像您所做的那样),以使它们对于所有实例都可用。为了明确您的意图,惯常做法是将构造函数命名以大写字母开头。


1
此外,按照惯例构造函数首字母应该大写。 - Davin Tryon
1
也就是说,一个旨在用作构造函数的函数通常最初是大写的。 - T.J. Crowder
@DavinTryon 这要看情况。我会将我的构造函数首字母大写,但这不是普遍的惯例。例如,可以查看我链接到的MDN页面上的示例。 - Denys Séguret

18

让我们举一个例子来理解Javascript中构造函数的产生。假设您被要求创建一个员工对象,它应该有4个属性:firstName,lastName,gender和designation。好吧!你说没问题。

var employee1={};
employee1.firstName="Anoop";
employee1.lastName="Rai";
employee1.gender="M";
employee1.designation="Software Engineer";
上面是最简单的方式,首先创建一个空对象,然后将所有4个属性关联到该对象(当然,您也可以通过内联方式创建相同的内容)。如果再次要求创建具有相同属性的另一个员工对象,该怎么办。
var employee2={};
employee1.firstName="Ram";
employee1.lastName="Kumar";
employee1.gender="M";
employee1.designation="Associate Software Engineer";

看起来一切都没问题。如果现在有人问你,总共有100名员工,而你只创建了其中2个,那么你需要再创建另外98个员工对象。现在你不会像上面那样繁琐地手动创建对象了。注意了!我们可以创建一个工厂方法,它将被调用任意次数,并创建对象,然后返回给我们。是的!只需编写一次,即可多次使用。

function createEmployeeObject(firstName, lastName, gender, designation){
  var employee={};
  employee.firstName=firstName;
  employee.lastName=lastName;
  employee.gender=gender;
  employee.designation=designation;
  return employee;
} 

var employee3=createEmployeeObject("Harry", "Dsouza", "M", "Project Manager");

非常便捷的方式,没有重复的代码。只需使用您的参数调用createEmployeeObject函数,然后您就可以得到您的对象。如果我们有若干种类型的对象,比如部门,那么我们也会有一个函数来创建一个部门对象并返回它。

那么,在这些函数中有什么共同点呢?它们是:

  1. 创建空对象
  2. var myObj = {};

  3. 在填充对象之后返回对象
  4. return myObj;

创建空对象并返回对象是创建对象的所有函数中都具有的共同点。Javascript已经创建了一种快捷方式,让您在使用创建对象函数时不必编写这些行。做到这一点的方法是使用构造函数。

在Javascript中,使用函数创建对象是相当普遍的,因此Javascript提供了一种快捷方式,让您编写创建对象的函数。这些特殊的函数称为构造函数。构造函数是一种让您填充需要创建的对象的函数。

function createEmployeeObject(firstName, lastName, gender, designation){
  this.firstName=firstName;
  this.lastName=lastName;
  this.gender=gender;
  this.designation=designation;
}
var employee4=new createEmployeeObject("Alan", "Marks", "F", "Business Analyst");

您必须了解这个关键字,它指向当前对象。请记住,在构造函数中,Javascript会为我们创建一个空对象,所以这实际上只指向那个对象。Javascript构造函数在填充完对象后会自动返回该对象。现在如何告诉Javascript一个函数是以构造函数模式调用的呢?就是使用new关键字,它告诉Javascript将一个函数视为构造函数。每次需要对象时,请使用new关键字调用函数,然后该函数会为我们准备一个对象并返回它。

即使Javascript不是基于类的,您也必须注意构造函数名称。不要使用驼峰命名法,使用常规命名法更好。

function Employee(firstName, lastName, gender, designation){
  this.firstName=firstName;
  this.lastName=lastName;
  this.gender=gender;
  this.designation=designation;
}
var employee5=new Employee("Mark", "Watson", "M", "DBA");

http://jkoder.com/javascript-constructors-why-it-should-be-used-object-oriented-programming-in-javascript/


5

Dystroy已经掌握了它。

换句话说,当使用new运算符调用函数时,该函数就会成为一个“构造函数”,并且会创建一个新的类实例

这也是提到函数名称中大写字母的约定原因,以便其他开发人员可以看出它是一个构造函数,并且符合当前命名的惯例。


大写首字母(驼峰式) - Rob Sedgwick

1
在面向对象编程中,类中的构造函数是一种特殊类型的子程序,用于创建一个对象。它准备新对象以供使用,通常接受构造函数用于设置所需成员变量的参数。
因此,var catC = new Cat("Fluffy", "White"); 创建了构造函数类 Cat 的一个新实例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接