代碼分析(一)
function Phone(ram) {
this.ram = ram;
this.call = function(){}
}
var p = new Phone("16GB");
var q = new Phone("32GB");
-
首先分析構造函數 Phone,定義一個 Phone 構造函數(因爲下面是要對此函數使用 new 操作創建新對象的,所以這裏說
Phone 是構造函數,其實如果說 Phone 是一個普通函數也是可以的)function Phone(ram) { this.ram = ram; this.call = function(){} }
注意:
- 在此圖中,並沒有
ram
和call
。ram
和call
是構造函數體裏的東西,是構造函數通過new
創建出的對象裏的屬性(絕對不要理解成是構造函數本身的屬性),也就是說this.ram=ram
,是新創建出來的對象裏面有個ram
屬性,值是創建對象時從外部傳遞進來的值。 - 構造函數本身有什麼屬性呢?構造函數本身有
name
屬性,凡是函數都有一個屬性叫做name
。比如Person
這個構造函數,它的name
屬性值就是Person
;而`var
person = function(){...};像這樣的聲明,
name屬性的值就是
person`。如下圖所示:
- 在此圖中,並沒有
以上代碼完整的圖如下所示:
代碼分析(二)
function Phone() {
this.ram = "16GB";
}
Phone.prototype.call = function(){}
var p = new Phone();
var q = new Phone();
-
Phone
構造函數中有prototype
原型屬性,此屬性指向原型 - 原型中有
constructor
屬性,此屬性指向構造函數 - 原型有
call
屬性,此屬性指向一個函數 - 通過
Phone
構造函數,實例化出了兩個對象,這兩個實例對象中分別都有__proto__
原型對象屬性,此屬性指向原型,與Phone
構造函數中的prototype
屬性指向的是同一對象 - 正是由於
p
和q
對象都指向同一個原型對象,所以當調用p.call()
或者q.call()
的時候,即使實例化對象本身中不存在此方法,此方法也會正常執行,因爲實例化對象中沒有,就會自動去原型中查找,原型中有,就調用了,這也就是原型繼承 - 開發中的用法是在構造函數中定義屬性,在原型中定義方法
代碼分析(三)
function Phone(){
this.ram = "16GB";
}
Phone.prototype = {
sayHello: function(){}
};
var p = new Phone();
var q = new Phone();
內存圖如下所示:
右上角的剛開始的原型對象(有constructor的),沒有任何屬性指向它了,時間長了,它就被回收了,但是在沒回收之前,它是存在的,並不是一沒有東西指向它了,它就消失了。