[英]What's the need for call() in prototypical inheritance
我在解析JavaScript中的原型繼承時遇到了一些麻煩,並考慮在此處發布。 考慮這個簡單的例子:
function Employee() {
this.name = "Rob";
this.dept = "R&D";
}
function Manager() {
//Employee.call(this);
this.reports = ["Report 1", "Report 2", "Report 3"];
}
Manager.prototype = Object.create(Employee.prototype);
Employee.prototype.type = "human";
m = new Manager();
console.log(m.name); //undefined
console.log(m.type); //human
我無法理解的是Employee.call(this)
這一行的效用。 既然我們要將Employee.protoype設置為Manager的原型,那么(我看到它)通過call()
明確強制在Employee中創建變量的需求是什么? 之前我認為可能是因為沒有Employee
對象存在,並且JS繼承在沒有對象的情況下無法工作,所以call()
在這里用於“完成對象構建”。 但是, type
屬性在Manager中反映出來而不需要call()
,這證明我們不需要硬對象來執行繼承(我的意思是,只是類類構造函數定義會這樣做)。
我希望我沒有把它變得太復雜。 簡而言之:為什么這里需要call()
,為什么屬性type
在沒有call()
情況下工作(如果call()
很重要,那就是)。
Employee.call(this)
的目的是向Manager實例添加名稱和部門屬性。
call()
的使用更符合慣例,它允許修改調用者(this)。
您通過原型界面后,屬性type
工作。
如果取消注釋Employee.call(this)
,則m.name將變為“Rob”。
即使原型是繼承的,也就是定義了'human'類型的地方,而沒有調用Employee,你不是“初始化基類”並在Employee()
構造函數中運行代碼。 僅僅因為Employee是Manager的原型並不保證您在創建管理器時想要運行Employee構造函數。
與某些可以調用super()
語言不同,您必須按名稱調用基類的初始化程序。 這類似於C ++:
class Manager : public Employee {
public:
Manager() : Employee() {}
};
您還可以決定何時調用父項並執行其他邏輯,其中自動調用不會為您提供該選項:
function Employee(name) {
this.name = name;
this.dept = "R&D";
}
function Manager(name) {
// Add the title to the name, first
var mgrName = name + ' (Manager)';
Employee.call(this, mgrName);
this.reports = ["Report 1", "Report 2", "Report 3"];
}
Manager.prototype = Object.create(Employee.prototype);
m = new Manager('Bill');
.type
(和其他原型繼承的屬性)確實有效。
但.name
和.dept
沒有,它們不是在m
創建的! 你是對的, Employee.call(this)
是完整初始化所必需的。 這是構造函數的super
調用,你不應該忽略它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.