0

Why this...

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

... when run through coffee -p test.coffee | node outputs this?

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

Why doesn't the password property show on console.log f ? Where is it stored and how is it retrieved?

2
  • 1
    You can just write coffee test.coffee you don't need to do the crazy. Commented Sep 12, 2012 at 20:09
  • @david I was trying to understand the generated code (hence the -p) and then sometimes I stuck | node in front of everything to run the code. Thank you for the tip anyways. ;) Commented Sep 12, 2012 at 20:37

2 Answers 2

3

The 'initial password' value is stored in Person.prototype.password. Person.prototype is an object with all the common attributes shared between Person instances. When you access aPersonInstance.password, the password property is first looked up in the aPersonInstance object; if it's not found there it will be looked up in its prototype, and then in its prototype's prototype and so on.

console.log f will not show f's prototype properties, only the properties stored in f themselves (also known as f's own properties). When you assign Bob's password with b.password = 'bob\'s password' you're creating a new password property in b itself, which will now be the value of accessing b.password, even though b's prototype still has the 'initial password' value. I hope that made some sense =P

By storing 'initial password' in the prototype you're sharing that value between all Person instances as a kind of default value. This is perfectly fine to do with strings or other primitive (immutable) types; but you have to take special care if you're going to do it with arrays or other mutable objects, because the same object will be shared between all the class' instances, and if one of them modifies it, e.g. @someArray.push 5, all the other ones are going to see it. In those cases, it's usually preferable to initialize the attribute in the class constructor, like @someArray = [], to guarantee that each instance will have a different array/object attribute.

Sign up to request clarification or add additional context in comments.

2 Comments

Good answer. I deleted mine, so you may want to edit the last paragraph a bit.
Thanks for the typo fixes, Mark-André. I've edited the last paragraph trying to mention what you suggested in your answer, as i think the the confusion of using mutable objects in the prototype and then getting unexpected results is quite recurrent =D
0

I want to give u a simple&quick answer but not exactly right in Javascript:

The variable password which you defined in class User is User.prototype.password, the variable just like class variable in OO language. It is not f's instance variable, so when you console.log f, u cant see password.

but if you retrieve f.password, then u will still get the value 'initial password'. when a instance cant find a variable in itself, it will continue finding it in its class, that is User.

b.password is a instance variable in b, so console can log it out.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.