2013-07-15 134 views
8

編輯:對於那些未來看到這篇文章的人來說,this site對我來說無疑是消化Javascript的關鍵。如果你來自傳統的面向對象的背景,我強烈推薦它。 UML-esq圖很棒。學習。原型

我仍然無法弄清楚Javascript中的.prototype屬性。它僅僅是對另一個對象的引用嗎?或者它是對另一個對象的指針的引用?我來自C/C++/x86,卻無法看到它是如何工作的。我們來看看我目前看到的東西的一些例子;它會幫助指出我的錯誤,看看事情是如何工作的。我甚至不知道其中的一些是否是有效的語法。 ObjectFunction分別是全局對象/函數對象。

1          // Global.prototype = ?? 
2          // Function.prototype = ?? 
3 
4 var obj1 = {};      // obj1.prototype = Object 
5 obj2 = {};       // obj2.prototype = Object 
6 
7 var func1 = function() {};   // func1.prototype = Function 
8 func2 = function() {};    // func2.prototype = Function 
9 function func3() {}     // func3.prototype = Function 
10 

我很困惑。

11 var Foo = function() { this.prop1 = 0; } 
12 var foo = new Foo();     // should it be 'new Foo' or 'new Foo()'? 
13 // Foo.prototype = Function 
14 // foo.prototype = Foo 
15 var Goo = function() { this.prop2 = 0; } 
16 var goo = new Goo(); 
17 // goo.prototype = Goo 
18 goo.prototype = new Foo(); 
19 // goo.prop1 now exists ? 

我也不明白交換原型。

20 function A() { 
21  this.prop1 = 1; 
22 } 
23 function B() { 
24  this.prop2 = 2; 
25 } 
26 function C() { 
27  this.prop3 = 3; 
28 } 
29 C.prototype = new B(); 
30 var c = new C(); 
31 // c.prop1 = 1 
32 // c.prop2 = 2 
33 // c.prop3 = undefined 
34 C.prototype = new A(); 
35 // c.prop2 = 2??? 
36 // c.prop3 = 3 

我無法理解這個概念。我不太明白。我不明白克隆對象如何獲得自己的本地數據副本,但對原始對象(原型)的更改以某種方式級聯到克隆。我一直在試圖FigureBug出來的東西擺弄周圍,但精神上我不能想出一個想法,是與每一個例子我見過

C++可能是一個巨大的怪物一致的,但至少我知道確切發生了什麼事。這裏...我用我最好的猜測.. 只是一個新的範式,我想。無論如何,如果你能幫忙,謝謝......我在這個原型上倒過來了。

+0

檢查我的回答這樣一個問題:http://stackoverflow.com/questions/17047025/trying-to-understand-javascript-inheritence/17049716#17049716 – Hoffmann

+0

如果你問obj.x和OBJ沒有它的自己的x屬性,JS會檢查obj.prototype.x的存在,如果存在,返回它,否則返回undefined。把它看作是編程的呼叫轉移,原型是可以嘗試訪問數據的備用數字。由於它是不同的電話,如果替代品被毀壞,您仍然可以撥打主線。 – dandavis

+0

@dandavis好的,我明白了。我不明白什麼.prototype引用,它默認設置爲什麼,以及當我開始交換原型的時候會發生什麼? – gone

回答

4

哇,這是很多問題。讓我們通過他們。

它僅僅是對另一個對象的引用嗎?或者它是對另一個對象的指針的引用?

JavaScript中沒有指針。然而,持有「一個對象」的變量或屬性實際上持有對該對象的引用,所以其他變量可以保存對同一對象的引用。

Global.prototype = ?? 

全局對象(如果你想window),其中所有的全局變量的定義,沒有原型(不關心在某些環境中的例外)。

我仍然無法理解JavaScript中的.prototype屬性。

.prototype屬性是所有函數對象都有指向其原型對象(普通對象)的屬性。

您不能將它與每個對象具有的內部參考原型混淆。 原型指向查找屬性的對象,而對象本身沒有屬性。

Function.prototype = ?? 

這是從中所有功能對象繼承的對象。它包含諸如callbind之類的內容。

var obj1 = {};    // obj1.prototype = Object 
var func1 = function() {}; // func1.prototype = Function 

是的,有點。我認爲你有這個概念,但不知道這個術語。雖然func.prototype是不同的事情,obj.prototype屬性甚至不存在。但是,您的意思是內部原型 - 我們可以通過Object.getPrototypeOf函數訪問它們。他們不引用構造函數,而是引用它們的原型對象。這裏的修正:

Object.getPrototypeOf(obj1) === Object.prototype 
Object.getPrototypeOf(func1) === Function.prototype 

它應該是 '新富' 或 '新的Foo()'?

這並不重要,它們是等價的。當你想傳遞參數時,你只需要明確的需要括號。

var Foo = function() { this.prop1 = 0; } 
var foo = new Foo(); 

同樣,你的假設是正確的,但表達錯誤。讓我們通讀細節。

上面我談到了「原型對象」。那些是什麼?它們是用每個函數隱式創建的普通對象。在這種情況下,它是Foo.prototype - 一個空的對象。所以我們在這裏處理三個對象:Foo構造函數,其Foo.prototype原型對象和foo實例。

foo有什麼特別之處?這是new運營商所做的第一件事。當一個函數被構造函數調用時 - 與new - 然後它的.prototype屬性被訪問,並且一個新對象被實例化,其內部原型被設置爲該原型對象。這是奇蹟般的事情。之後,在新實例上調用該函數,以便this是新對象;在你的情況下,它會在實例上創建.prop1屬性。然後返回結果(並分配到foo)。

如何利用這個魔法呢?重點是在原型對象上創建屬性,然後繼承它。

// modify `Foo.prototype`, the object which `foo` inherits from: 
Foo.prototype.prop2 = 1; 
console.log(foo.prop2); // 1! 

我也不太瞭解周圍交換原型。

的問題是,這是完全不可能的。一旦實例化,對象的原型鏈就非常靜態。但是,你並不需要經常這樣做。

goo.prototype = new Foo(); 

這並沒有工作,因爲.prototype屬性是不是你所期望的。

var c = new C(); 
C.prototype = new A(); 

這不工作只是littlebit。看一下new的作用 - 它只查找構造函數的.prototype屬性一次。內部原型保持鎖定,然後 - 您不更改c實例。但是,如果您現在要創建一個新實例var d = new C(),那麼它將從A實例繼承。

我希望這有助於;如果您還有其他問題,請發表評論。

+0

對不起,我遲到了。但是,是的。就是這個。 「問題是,這是不可能的」:正是我所需要的(以及你提到的其他一切)>非常感謝;頂尖的答案伊莫 – gone

2

原型用於在讀取期間對象本身沒有定義的情況下搜索屬性。寫操作總是對象本身發生

當你調用

// An instance of Foo ({prop1:0}) is set as the 
// prototype (to all instances of Goo) 
var goo = new Goo(); 

// 0, from the prototype 
console.log(goo.prop1); 

// Read from the object itself (set in Goo's constructor) 
console.log(goo.prop2); 

// New instance, same prototype as goo 
var goo2 = new Goo(); 
console.log(goo2.prop1) ; // 0, still from the prototype 

// Setting is always at the object level, not the prototype 
goo.prop1 = 5; 

// goo2 is still reading from the prototype 
console.log(goo2.prop1); 

注:

不要實例化父類來設置繼承。看看這裏爲什麼http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html