2014-02-17 68 views
2

延長比方說我有這樣的:的JavaScript構造

function Foo(){ 
    this.name = "fooos"; 
}; 

現在後面的腳本我有Foo參考,什麼時候實例化將屬性添加到富。我可以做這樣的事情:

Foo.prototype.myProp = 3; 

foo = new Foo(); 

expect(foo).to.have.property('name'); 
expect(foo).to.have.property('myProp'); 

這個偉大的工程,直到我需要一個對象附加到原型,像這樣:

Foo.prototype.myProp = { bar : 3 }; 

的問題是,現在情況將在bar共享狀態(如`酒吧只是一個參考):

foo = new Foo(); 
foo2 = new Foo(); 

foo.myProp.bar = 5; 
expect(foo2.myProp.bar).to.equal(5); 

這是不可取的。但是,如果該對象添加到構造函數中,則實例不會共享狀態。

有沒有辦法解決這個問題?我無權訪問構造函數來操作它。我需要將一個對象附加到原型中的實例。

回答

6

屬性不必是對原型,你可以直接添加到實例:

var f = new Foo(); 
f.myProp = { bar: 3 }; 

我知道。它不是我想要的。

我能想到的通過原型與財產做到這一點的唯一方法(而不是方法; @meager使用方法a solution)是一個醜陋的黑客在其中定義的原型Object.defineProperty屬性(ES5-只),然後重新定義上第一接入,例如:

Object.defineProperty(Foo.prototype, "myProp", { 
    get: function() { 
     var obj = { bar: 3 }; 
     Object.defineProperty(this, "myProp", { 
      get: function() { 
       return obj; 
      }, 
      set: function(value) { 
       obj = value; 
      } 
     }); 
     return obj; 
    } 
}); 

Live Example | Source

我會不是推薦。 :-)


另一種方法是拋出一個門面在Foo前,像這樣:

var OriginalFoo = Foo; 
Foo = function() { 
    OriginalFoo.apply(this, arguments); 
    this.myProp = { bar: 3 }; 
}; 
Foo.prototype = Object.create(OriginalFoo.prototype); 

那會,當然,僅通過new Foo適用於創建的對象此之後代碼執行。

+0

我知道。它不是我想要的。 – Fresheyeball

+3

這是不是你想要的?從你的問題來看,這似乎是*你想要的。 – Oswald

+0

如果腳本稍後會創建另一個'Foo'的實例,它將不會附加'myProp'。我希望它是構造函數的一部分。 – Fresheyeball

2

你不能這樣做,因爲你需要通過原型的限制。原型是共享的,你不能通過原型給每個實例一個獨特的對象。定義原型是什麼幾乎是不可能的。

最接近的事是增加一個訪問方法,它懶洋洋地增加了財產的具體情況,但這是很遠,從刪除您的問:

Foo.prototype.getMyProp = function() { 
    this.myProp = this.myProp || { bar: 3; } 
    return this.myProp 
} 

foo = new Foo(); 
foo2 = new Foo(); 

foo.getMyProp().bar = 5 
expect(foo2.getMyProp().bar).to.equal(3); 
+0

可以工作,如果使用的方法是可以接受的OP。 –