2011-07-01 146 views
4

我想了解JS原型屬性:我的示例代碼JavaScript的原型

function Container(param) { 
    this.member = param; 
} 

var newc = new Container('abc'); 


Container.prototype.stamp = function (string) { 
    return this.member + string; 
} 

document.write(newc.stamp('def')); 

function Box() { 
    this.color = "red"; 
    this.member = "why"; 
} 

Container.prototype = new Box(); 
Box.prototype.test = "whatever"; 
var b = new Box(); 

document.write(newc.test); 

這裏的最後一行是不確定的 - 儘管集裝箱的原型是一個儲物箱和箱的原型有一個屬性測試,爲什麼是NEWC這是指在框中測試不起作用?任何人都可以解釋'Prototype'是如何在我的上下文中工作的。

謝謝...

+1

作爲@The Scrum Meister說,你在實例創建後設置'Container'的'prototype'。該實例仍將指向舊的原型。 –

+0

你可以評論你的問題的答案,你不必「編輯」答案。 –

+1

@FelixKling我不認爲你可以評論,如果你有1的評價:s – Neil

回答

2

您的newc實例之後設置Container原型Box()已經創建。

重新排序聲明如下:

function Container(param) { 
    this.member = param; 
} 

function Box() { 
    this.color = "red"; 
    this.member = "why"; 
} 

Container.prototype = new Box(); 
Box.prototype.test = "whatever"; 
Container.prototype.stamp = function (string) { 
    return this.member + string; 
} 

//Here the containers prototype setup is complete. 
var newc = new Container('abc'); 

document.write(newc.stamp('def')); 

document.write(newc.test); 
+1

我認爲這個例子會更好,如果你定義的實例,然後設置「Box.prototype.test =」任何「;'屬性。這將使得它更清楚,唯一的「有問題」的行是'Container.prototype = new Box();'。 –

0

的對象不包含它的構造函數的引用它使用得到的原型。如果確實如此,那麼代碼將按照您的預期工作。

而是,一個對象包含對其原型的引用,該原型在創建時會被設置。

從語言規範部分4.2.1

由構造器創建的每個對象都有一個隱式引用(稱爲對象的原型),其構造的「原型」屬性的值。此外,原型可能有一個對其原型的非空隱式引用,等等;這被稱爲原型鏈。當對對象中的某個屬性進行引用時,該引用就是該原型鏈中包含該名稱屬性的第一個對象中該名稱的屬性。換句話說,首先直接提到的對象是檢查這樣的屬性;如果該對象包含指定的屬性,那就是引用引用的屬性;如果該對象不包含指定的屬性,則接下來檢查該對象的原型;等等。

2

如果聽起來像你想知道爲什麼它的行爲是這樣,而不只是「修復」代碼。所以這就是發生了什麼。正如你所看到的,如果你改變了「容器」的原型,你實際上會改變已經實例化的新對象和對象的屬性。所以:

function Container(param) { 
    this.member = param; 
} 

var newc = new Container('abc'); 

// setting a new property of the prototype, after newc instantiated. 
Container.prototype.stamp = function (string) { 
    return this.member + string; 
} 

// This already-instantiated object can access the stamp function 
document.write(newc.stamp('123')); // output: abc123 

因此,有上述沒有問題,只要它被定義之前,你不叫新方法。下一點。此添加到上述:

// Our Box object 
function Box() { 
    this.color = "red"; 
    this.member = "why"; 
} 

Container.prototype = new Box(); 
var newd = new Container('fgh'); 
document.write(newd.stamp('456')); // output: ERROR 

錯誤!但這是有道理的,對吧?你完全消滅了「容器」原型,並將其替換爲「盒子」中沒有「印章」功能的原型。

我打算假設你想要「盒子」從「容器」繼承。這從命名慣例是合乎邏輯的。如果你想這樣做,這個替換上一節:

// Our Box object 
function Box() { 
    this.color = "red"; 
    this.member = "why"; 
} 

// This inherits from Container. Note that we can 
// do this before or after we declare "Box" 
Box.prototype = new Container(); 

Box.prototype.test = "Whatever"; 
var b = new Box("jkl"); // note: "jkl" is ignored because "Box" sets "member" to "why" 

document.write(b.test); // output: Whatever 
document.write("<br>"); 
document.write(b.stamp("345")); // output: why345 

所以現在我們有一個「盒子」,它可以調用自己的方法和參數,並從其父「容器」給他們打電話。

所以,大的情況是,一個對象會查看它自己的方法或原型的原型,如果它沒有找到它,它會看到它繼承的東西的原型,等等。另一個重點是在原型中設置一些東西使得它可以立即在該對象的所有將來和當前實例中使用。

+0

你在最後一段中丟失了我......在Box例子中,Box的原型現在是Container,對吧?從你的陳述來看,Box會有一個原型,檢查它,如果它沒有在那裏使用容器的原型。 –

+0

@justnS,Box最初將其原型設置爲實例化的Container對象。這使Box繼承Container。之後,我們直接在Box原型中設置更多參數。這將創建新的參數或覆蓋從Container繼承的參數。清除泥漿? – TheGerm