3

I'm trying to create a builder pattern in Javascript that uses private variables, while providing one public accessor (fullName) that returns a mashup of all the other properties. This question and answer suggests that I can use Object.defineProperty inside the person constructor in order to access private variables, but it doesn't work - instance.fullName is always undefined.

How can I get this working so that the builder pattern variables remain private, but the public accessor has access to them throughout the build chain?

var Person = function () {
    var _firstName, _lastName

    Object.defineProperty(this, "fullName", {
        get: function () {
            return _firstName + ' ' + _lastName;
        }
    });

    return {
        firstName: function (n) {
            _firstName = n
            return this
        },
        lastName: function (n) {
            _lastName = n
            return this
        }
    }
}

var x = new Person().firstName('bob').lastName('dole');

console.log(x.fullName); // always undefined
Community
  • 1
  • 1
brandonscript
  • 68,675
  • 32
  • 163
  • 220
  • I suspect it's because the object being returned from `Person` is different from the `this` on which `Object.defineProperty()` is called. – Matt Ball Nov 27 '15 at 19:38
  • Hmmmmm yeah, frankly `Object.defineProperty()` doesn't really feel like the right way to go about this anyway. – brandonscript Nov 27 '15 at 19:41
  • If I have to do it with public properties, that's fine, but even using `this._firstName` etc. doesn't work with this design. – brandonscript Nov 27 '15 at 19:48

1 Answers1

3

As per my comment, change the object passed to defineProperty():

var Person = function () {
    var _firstName, _lastName

    var _self = {
        firstName: function (n) {
            _firstName = n
            return this
        },
        lastName: function (n) {
            _lastName = n
            return this
        }
    }

    Object.defineProperty(_self, "fullName", {
        get: function () {
            return _firstName + ' ' + _lastName;
        }
    });

    return _self;
}

var x = new Person().firstName('bob').lastName('dole');

console.log(x.fullName); // bob dole

http://jsfiddle.net/mattball/peztf9qs/

Matt Ball
  • 354,903
  • 100
  • 647
  • 710