我试图理解这段代码,并想知道为什么我们在子“class”构造函数中调用超级构造函数:
function Person(name) {
this.name = name;
}
// Other properties on Person prototype here...
function Employee(id, name) {
Person.call(this, name); // Why do we have to do this?
this.id = id;
}
Employee.prototype = Object.create(Person.prototype);
// Other properties on Employee prototype here...
1)为什么我们有 Person.call(this, name)
?在"Secrets of the Javascript Ninja"中,它们执行 prototype
继承 WITHOUT 调用超级构造函数(其余代码是相同的,除了 Object.create
,但我明白为什么需要这样做) .
2 回答
所以这是您的Employee(和Person)的原型链,没有
Person.call(this,name)
行:每当您请求员工的 property 时,JavaScript都会沿着原型链向下查找该属性 . 如果你写这个:
JavaScript将在
employee
中查找,而不是在employee.[[prototype]]
中,然后在employee.[[prototype]].[[prototype]]
中(按照图中的箭头方向),直到找到属性walk
.如您所见,如果您请求属性
name
,JavaScript将无法找到它,因为它不在employee
的原型链中 . 所以你必须确保"copy"本地属性,如name
和sex
.您可以通过使用当前
Employee
的上下文调用Person
的构造函数来执行此操作:这与您在Employee构造函数中复制Person构造函数内部的所有代码基本相同:
这导致以下设置和具有name属性的员工:
不调用super的构造函数意味着子类对超类的行为有一些了解:这与封装相反 . 它不应该知道父类是否需要或不需要在其构造函数中使用任何类型的“设置” . 为了安全起见,它应该简单地称之为并继续 .
例如,如果Person总是必须在实例化时初始化一堆属性,而Employee没有调用Person构造函数,那么依赖Person属性/方法的Employee实例操作可能无法正常运行 .