對象和構造
一個你必須在javascript習慣的事情是,構造函數是類。儘管ES6確實引入了class
關鍵字和類語法,但它僅僅是底層機制的語法糖。架構沒有改變。
原型是構造函數將用於實例化新對象的構造函數的屬性。所以,例如,如果你想創建大量的「人」,你會寫這樣的東西:
function Person (name) {
this.name = name;
}
Person.prototype = {};
Person.prototype.name = "";
Person.prototype.age = null;
Person.prototype.gender = null;
請注意一些事情。與其他OO語言相比,這基本上是顛倒的。在其他語言中,您可以定義一個類,然後可以將構造函數定義爲該類的特殊屬性/方法。在JavaScript中,您定義了一個構造函數,然後將該類(原型)定義爲該構造函數的特殊屬性。
二,沒有特別的關鍵字constructor
。構造函數只是一個常規函數。沒有什麼特別的。它才成爲一個構造函數,如果你調用使用new
關鍵字是:
var x = Person(); // regular function, x is undefined
var y = new Person(); // constructor, y is an instance of Person
所以,因爲沒有什麼可以告訴一個程序員的天氣函數是一個構造函數或JavaScript程序員已經開發出一種約定,其中功能的普通函數名稱始終以小寫字母開頭,構造函數名稱始終以大寫字母開頭。從上面的代碼中,您可以看到名爲Person
的函數,因此您可以假設我打算將它作爲構造函數。
繼承
因爲原型是,嗯...一個對象的原型,那麼從您孩子的原型設定爲父母的原型實例的構造繼承。在現代的JS,你可以這樣做:
function Employee (name, job) {
this.name = name;
this.job = job;
}
Employee.prototype = Object.create(Person.prototype); // Inherit!
Employee.prototype.job = null;
請注意,我們從一個對象(原型)繼承,因爲在JavaScript中你的對象,而不是構造函數,而不是類繼承。
其次,請注意,我們通過將我們的原型設置爲副本來繼承我們父級的原型。這是因爲,如果我們只是將父母的原型分配給我們自己的原型,那麼當我們添加新的屬性時(如本例中的job
),我們不想修改父母的原型(因爲那樣不會是繼承)。
在之前的Object.create
功能存在的日子裏,你最好別這樣做:
Employee.prototype = new Person();
這是今天仍然有效,即使Object.create
一般是優選的。所以在RxJS代碼中,當你看到這個時:
child.prototype = new __();
這就是繼承發生的地方。請記住,原型是構造函數用作模板來創建新對象的內容。所以,上面的線:
__.prototype = parent.prototype;
意味着我們現在有一個函數__
這將創建一個類似於父母會創建的對象的對象。所以做new __()
會創建一個類似於調用父構造函數但不執行父構造函數中定義的任何邏輯的對象。所以基本上它的做法與Object.create(parent)
類似;
繼承只是將父級原型的副本分配給我們自己的原型。以上所有其他複雜的比特僅僅是準備複製父母的原型。
無論下面的答案是** **精準,認爲原型鏈爲'單向鏈接list'(EVAL時爲'(讓新的兒童()) - 丙'你從葉去根直到空。你在上面畫的圖是偉大的,除了所有的'constructor'關係是錯誤的。正如代碼明確地說'child.prototype.constructor = child','constructor'是它自己的原型只是一個普通的道具。 – Xlee
是,我不確定是否正確繪製了構造函數鏈接,但我確定它不是'child.prototype.constructor'。它表示'this.constructor = child',這裏'this'是指新對象創建(粉紅色框),所以構造函數鏈接應該從粉紅色框鏈接到孩子fn,或者從綠色框(粉紅色框)到孩子fn,我不能說出這兩個是哪一個正確。@Xlee – kevguy
我知道你的意思,指的是關鍵在js中(這是應用函數的所有者/調用者/上下文)中的'this'的d,顯然在你的情況下,'this'表示'child.prototype'由構造函數創建的新實例(根據你的圖) – Xlee