2013-04-09 54 views
2

我刚刚进入咖啡脚本,并且在解决类扩展如何工作时遇到问题。看来,定义为父类的实例属性的属性在扩展该类时正在实现为静态属性。使咖啡脚本中的类扩展和实例属性有意义

我有一个名为Foo的类,我想用它作为两个子类Bar和Goo的基类。我给富实例属性称为foobs并添加foob,像这样的方法:

class Foo 
    foobs:[] 
    addFoob: (foob) -> 
     @foobs.push(foob) 

我延长美孚酒吧和咕,并创造新的情况下,像这样:

class Bar extends Foo 
    otherMethod: -> 
     alert 'doing other stuff' 

class Goo extends Foo 
    secondMethod: -> 
     alert 'doing second stuff' 

barInstance = new Bar() 
gooInstance = new Goo() 

但是当我添加一个Foob到barInstance时,它也被添加到gooInstance!

barInstance.addFoob('test') 

console.log gooInstance.foobs (outputs ["test"]) 

很明显,我在这里做错了什么。我希望barInstance和gooInstance每个都有自己的“foobs”属性,但由于某些原因,尽管foobs是Foo上的一个实例属性,但它被分配为Bar和Goo上的类属性。任何想法如何解决这个问题?或者也许有不同的语法,我不知道?

感谢

回答

3

问题在于你如何声明foobs - 你真的希望它在实例上,所以它应该在constructor函数中声明。目前它在所有实例共享的prototype上声明。如果我们看一下你在做什么Foo声明编译成,我们可以看到这样的话:

class Foo 
    foobs:[] 
    addFoob: (foob) -> 
    @foobs.push(foob) 

编译为:

var Foo = (function() { 
    function Foo() {} 
    Foo.prototype.foobs = []; 
    Foo.prototype.addFoob = function(foob) { 
    return this.foobs.push(foob); 
    }; 
    return Foo; 
})(); 

你想要做什么是声明这样一个构造函数:

class Foo 
    constructor: (@foobs = [])->  
    addFoob: (foob) -> 
    @foobs.push(foob) 

这会foobs阵列添加到Foo每个实例。

+0

感谢您的所有答案!接受这个是因为方法参数(@foobs = [])的内联语法很酷,我总是为无法在JavaScript中执行而感到恼火。 – jraede 2013-04-09 03:29:32

1

foobs阵列应该在构造函数初始化,因为现在,因为你在prototype定义了它的所有实例将共享相同的foobs阵列。

您可以安全地定义原始值prototype,因为这些值是不可变的,但是您应该避免将对象存储在prototype中,除非希望这些值在所有实例之间共享。

+0

如果可以的话,我会赞成这一个。感谢关于原型上对象的解释。 – jraede 2013-04-09 03:32:48

2

这是因为您将阵列放置在Foo原型上,因此它将在所有实例中共享。相反,您需要为Foo的每个实例创建一个数组,然后直接添加它。它

class Foo 
    foobs:null, # This isn't needed, but it's good for documentation. 
    constructor: -> 
    @foobs = [] 
    addFoob: (foob) -> 
    @foobs.push(foob) 

展望不同,你有什么本质上是:

sharedFoobs = [] 

class Foo 
    foobs: sharedFoobs 

这使得它更清晰一点,一个新的阵列,从未创建。