MDN JavaScript指南中的“构造函数中的全局信息”,小查询

时间:2014-02-21 16:20:05

标签: javascript inheritance constructor

在MDN JavaScript指南的“Property inheritance revisited”部分下,它解释了属性继承的一些细微之处。

我特别感兴趣的是一个关于递增id的例子:

var idCounter = 1;

function Employee (name, dept) {
this.name = name || "";
this.dept = dept || "general";
this.id = idCounter++;
}

function Manager (name, dept, reports) {...}
Manager.prototype = new Employee;

function WorkerBee (name, dept, projs) {...}
WorkerBee.prototype = new Employee;

function Engineer (name, projs, mach) {...}
Engineer.prototype = new WorkerBee;

function SalesPerson (name, projs, quota) {...}
SalesPerson.prototype = new WorkerBee;

var mac = new Engineer("Wood, Mac");

基本上,它继续说这个的完整版本(每个构造函数都有一个'base'属性,它也在原型链中调用它们上面的构造函数)将意味着mac.id将是5.

据我所知,每次创建一个Employee对象时,id值都会增加1,但是在创建'mac'之前4次确实创建了一个Employee对象? 如果有人能够一步一步地给我这个过程,我将不胜感激。

编辑 - 相关网页:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model#Global_information_in_constructors

2 个答案:

答案 0 :(得分:3)

使用new将调用构造函数。每当调用构造函数时(通过new或通常的方式()callapply),id都会递增。所以我们算一下:

Manager.prototype = new Employee; //1
//...
WorkerBee.prototype = new Employee; //2

到目前为止这是两个。如果你在代码下考虑这个重要的句子:

  

进一步假设此处省略的定义包含base   property和在原型链中调用它们上面的构造函数

这基本上意味着代码中的{...}部分是这样的:

function Manager (name, dept, reports) {
    Employee.apply(this, arguments);
}

This jsFiddle显示没有这些省略号的代码(最小化实现)。

所以这些都会调用Employee函数:

Engineer.prototype = new WorkerBee; //3
//...
SalesPerson.prototype = new WorkerBee; //4
//...
var mac = new Engineer("Wood, Mac"); //5

答案 1 :(得分:0)

John Resig在how to use class-based inheritance上有一篇优秀的文章和简单的帮助函数。这使得从基类继承更容易,而无需调用构造函数。

这是我自己的解释:

为了使Manager继承EmployeeManager.prototype实际上必须是Employee实例。因此,Manager.prototype = new Employee实际上会立即执行Employee构造函数。

解决这个问题的唯一方法是将构造函数逻辑放入一个单独的方法,例如init

function Employee() { /* EMPTY CONSTRUCTOR */ }
Employee.prototype.init = function(name, dept) {
  this.name = name || "";
  this.dept = dept || "general";
  this.id = idCounter++;
}

function Manager(name, dept, reports) {
    this.init(name, dept); // Calls the base constructor
}
Manager.prototype = new Employee();