2014-03-31 66 views
6

我想了解在JavaScript中的原型。 例如:替代(或相同?)作爲JavaScript原型

1)

var MyObject = function() { 
    this.a = "a"; 
    return this; 
} 

MyObject.prototype.fn = function() {console.log('1');} 


var obj1 = new MyObject1(); 

2)

var MyObject = function() { 
    this.a = "a"; 
    this.fn = function() {console.log('1');} 
    return this; 
} 

var obj2 = new Object2(); 

我得到OBJ1OBJ2作爲相同。那麼,我在做什麼2)也是原型?或不?關於原型我錯過了什麼?

+1

[爲什麼原型繼承問題](http://aaditmshah.github.io/why-prototypal-inheritance-matters「爲什麼原型繼承問題| Aadit M Shah」) –

+1

只需將'MyObject.prototype'作爲一個對象這是由'MyObject'構造函數創建的所有對象共享的。因此,即使您從「MyObject」創建1,000個新對象,它們也將共享(繼承).prototype對象的所有屬性。 –

+0

感謝您的所有意見和解答。 +1。我必須選擇一個作爲答案。 –

回答

1

obj1和obj2稍有不同,我會給你一個關於JavaScript中prottypal繼承的快速解釋。

原型是一個對象,就像任何其他對象一樣。

每個擁有原型的對象都會從中繼承所有的屬性和方法,並在它們已經在對象中定義的情況下覆蓋它們。原型引用是實時的,這意味着,無論何時修改作爲另一個對象的原型的對象,這些更改都會反映在該對象中。

您正在使用僞古典繼承方法,通過您定義的Constructor函數將返回「類」的實例。該類的所有實例都將作爲其原型對象定義的對象爲:Constructor.prototype,您可以向該原型添加方法或屬性,並將這些方法或屬性添加到「類」的每個實例中。

爲什麼obj1和obj2不同?

obj1不持有對fn方法的直接引用,而是它持有對具有該方法的原型的引用,因此obj1也具有該引用。

obj2有一個方法的直接引用,這意味着它是對象的一個​​屬性。

您可以通過更改原型的方法來更改obj1的fn方法,並且任何其他MyObject實例(如obj1)也將被更改。

但是你不能在obj2中做到這一點,如果你修改obj2的方法,你只需要替換該實例的方法。

我希望你有什麼,只是問你是否有任何疑問。

關於寫作「類」:JavaScript沒有類,它模仿了原型的類繼承,你可以使用粗糙的原型繼承,使用Object.create,你會發現它更容易。

4

2)不原型

下面是一個簡單的例子,這也解釋了這兩種方法的區別在於:)


var MyObject1 = function() { 
    this.a = "a"; 
    return this; 
} 

MyObject1.prototype.fn = function() {console.log('1');} 

var obj1 = new MyObject1(); 

// change the prototype again 
MyObject1.prototype.fn = function() {console.log('2');} 

var obj2 = new MyObject1(); 

obj1.fn(); // logs '2' 
obj2.fn(); // logs '2' 

在這裏你可以在肌酸之後改變原型對象g obj1,但是這種改變會影響對象,因爲它具有對當前原型對象的引用。

因爲obj2也具有對原型對象的引用,所以通過調用函數fn也可以得到'2'。

這裏所有實例共享相同的原型對象。


2)

var MyObject2 = function() { 
    this.a = "a"; 
    this.fn = function() {console.log('1');} 
    return this; 
} 

var obj3 = new MyObject2(); 

// change the function 
obj3.fn = function() {console.log('2');} 

var obj4 = new MyObject2(); 

obj3.fn(); // logs '2' 
obj4.fn(); // logs '1' 

這裏每個對象都有它自己的fn功能。如果一個對象改變了這個函數,它只會影響當前對象。

1

說我們有

var A = new Object1(), 
    B = new Object1(), 
    X = new Object2(), 
    Y = new Object2(), 
    fn2 = function() { 
     console.log(2); 
    }; 

考慮:(重置每個)

    • A.fn === B.fn; // true
    • X.fn === Y.fn; // false
    • Object1.prototype.fn = fn2然後A.fn(); // 2
    • Object2.prototype.fn = fn2X.fn(); // 1
    • A.fn = fn2現在A.fn(); // 2B.fn(); // 1
    • X.fn = fn2現在X.fn(); // 2Y.fn(); // 1
    • "fn" in A; // trueA.hasOwnProperty("fn"); // false
    • "fn" in X; // trueX.hasOwnProperty("fn"); // true

我們可以從中學到什麼?
跨實例的原型分享,但不直接在其上設置屬性,而在構造函數中設置屬性會每次創建新的和單獨的屬性。