5

The following doesn't work, from my getter, I can't see _nickname defined in the 'class' Person.

var Person = function (args) {

    var _nickname = '';
    if (args === undefined || args === null) {
        return;
    }
    if (args.nickname !== undefined && args.nickname !== null) {
        _nickname = args.nickname;
    }

}

Object.defineProperty(Person.prototype, "nickname", {
    get : function () {
        return _nickname;
    }
});

var x = new Person({
        nickname : 'bob'
    });

console.log(x.nickname);

How should one go about accomplishing this? Is there a way of adding _nickname to the prototype of Person from within its function?

3
  • Quick tip: args === undefined || args === null same as args == null because null == undefined. Same thing with other comparison. Commented Aug 21, 2013 at 22:14
  • Ah yeah, I was being finicky about JsLint and he doesn't like the ==. I corrected it. I don't know if I'm being too cautious, but I was hoping JS closure would take care of it :-) Commented Aug 21, 2013 at 22:15
  • 3
    JSHint is my cup of tea. It has an option just for this particular case: eqnull Commented Aug 21, 2013 at 22:17

1 Answer 1

6

Is there a way of adding _nickname to the prototype of Person from within its function?

If you mean the Person constructor, sure (although in my opinion it doesn't look very elegant):

var Person = function (args) {
    var _nickname = '';
    if (args === undefined || args === null) {
        return;
    }
    if (args.nickname !== undefined && args.nickname !== null) {
        _nickname = args.nickname;
    }
    Object.defineProperty(this, "nickname", {
        get : function () {
            return _nickname;
        }
    });
}

var x = new Person({
    nickname : 'bob'
});

console.log(x.nickname);

http://jsfiddle.net/JEbds/

In this case, your getter is just another closure, so it has access to _nickname. And it's not on the prototype anymore, you need an own property to accomplish that.

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

8 Comments

But won't Object.defineProperty run every time I do 'new Person()'? Or is that not a big deal? That's really what I wanted to avoid.
It does. But if you don't run it from the constructor, it will never be able to access _nickname.
@Matt If you're okay with it not being really private, you can use this._nickname (and you can even set it writable: false, so the value set in the constructor can never be changed). jsfiddle.net/669Gb
@bfavaretto Note that if you were to use defineProperty to define the string value _nickname it would not be writable (because string is immutable) but if _nickname were a mutable object it will be writable (not directly but through the object's functions). Let's say _nickname is an array and in the Person constructor we do: Object.defineProperty(this, "_nickname", {value:[]}) with a person instance we do p._nickname=22; then nothing will happen and _nickname is still [] but if we do: p._nickname.push(22); Then p._nickname will be [22].
@Matt There is realy no good way to have private instance value properties (properties that have unique private values for each instance). You can have shared "private" functions on the prototype or shared value property where the value is shared among all instances. "Private" functions: stackoverflow.com/questions/18320934/… Using constructor functions and prototype: stackoverflow.com/questions/16063394/…
|

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.