2012-09-12 55 views
0

为什么这...继承与CoffeeScript的

class Person 
    name: "initial name" 

    constructor: (@name) -> 


class User extends Person 
    password: "initial password" 


f = new User "Felds" 

console.log f 
console.log "my name is '#{f.name}' and my password is '#{f.password}'" 

b = new User "Bob" 
b.password = "bob's password" 

console.log b 

...当通过coffee -p test.coffee | node输出这个运行?

{ name: 'Felds' } 
my name is 'Felds' and my password is 'initial password' 
{ name: 'Bob', password: 'bob\'s password' } 

为什么不上console.log fpassword物业展?它在哪里存储,它是如何检索的?

+1

你可以直接写'coffee test.coffee'你不需要做这个疯狂的事。 – david

+0

@david我试图理解生成的代码(因此'-p'),然后有时我坚持'|节点“的前面,以运行代码。无论如何,谢谢你的提示。 ;) –

回答

3

'initial password'值存储在Person.prototype.password中。 Person.prototype是具有在Person实例之间共享的所有常见属性的对象。当您访问aPersonInstance.password时,首先在aPersonInstance对象中查找密码属性;如果没有找到它,它将在其原型中查找,然后在其原型的原型中查找,等等。

console.log f不会显示f的原型的属性,只存储在f自身的属性(也称为f自己属性)。当你与b.password = 'bob\'s password'分配Bob的密码你在b本身创建一个新的password属性,现在将要访问b.password的价值,即使b的原型仍具有'initial password'值。我希望这是有道理的= P

通过将'initial password'存储在原型中,您将在所有Person实例之间共享该值作为一种默认值。这对于字符串或其他基元(不可变)类型来说是完美的。但是如果要使用数组或其他可变对象来处理,则必须格外小心,因为同一对象将在所有类的实例之间共享,并且如果其中一个对象修改了它,例如, @someArray.push 5,所有其他人都会看到它。在这些情况下,通常最好在类构造函数中初始化属性,如@someArray = [],以保证每个实例具有不同的数组/对象属性。

+0

很好的答案。我删除了我的,所以你可能想编辑最后一段。 –

+0

感谢您的错字修复,马克安德烈。我已经编辑了最后一段,试图提到你在答案中提出的建议,因为我认为在原型中使用可变对象的困惑,然后得到意想不到的结果是相当复杂的= D – epidemian

0

我想给ü简单&快速的答案,但不完全正确的Javascript:

变量password您在class User定义为User.prototype.password,变量就像类变量在面向对象的语言。 它不是f的实例变量,所以当你console.log f,你不能看到password

但如果你检索f.password,那么你仍然会得到值'initial password'。当一个实例本身无法找到变量时,它将继续在其类中找到它,即User

b.passwordb中的一个实例变量,所以console可以注销它。