wootscootinboogie
wootscootinboogie

Reputation: 8695

Getters and setters on prototype

Consider the following little bit of JavaScript: (I'm not worried about backward compatibility and I don't want to use anything that will soon be deprecated).

  var Person = (function () {
            var _age,
                _name;
            function age(num) {
                if (!num) {
                    return _age;
                }
                else {
                    _age = num;
                }
            }
            function name(val) {
                if (!val) {
                    return _age;
                }
                else {
                    _name = val;
                }
            }
            return {
                age: age,
                name: name
            }
        })();
        console.log(Person.age()); //undefined
        Person.age(100);
        console.log(Person.age()); //100

(not sure how useful this will be, if I wanted to do something polymorphic the prototype here is still Object.)

vs. (constructor inside iffy, closure allows name and val accecss to _name and _val

  var Person = (function () {
            var _age,
                _name;
            function Person(options) {
                _age = options.age;
                _name = options.name;
            }
            Person.prototype.age = function (val) {
                if (!val) {
                    return _age;
                }
                else {
                    _age = val;
                }
            }
            var test = new Person({ age: 100, name: 'jon' });
            console.log(test.age());//100
           //if I want to do with Person objects outside of this script I should
           //return something
        })();

(this allows for the standard property styles I'm looking for (a null parameter return a value and passing a parameter will set that value

function Person(age, name) {
        //i don't want to add get and set methods to each instance of Person
        }
        Person.prototype.age = function (num) {
            if (!num) {
                //what to return if nothing is passed to age?
                return //what?
            }
            else {
                //x = num
                //what would x be?
            }
        }

I need to be able to perform some actions polymorphically based on the prototype. The last code snippet is the easiest to read, but it doesn't offer the get/set succintness I'm looking for. The first code snippet will let me Object.create nicely enough but it has Object as the prototype. If I want get/set methods like obj.test() to get and obj.test(100) to set, how can I achieve this adding methods to the prototype and not inside the constructor itself?

Upvotes: 2

Views: 1513

Answers (2)

Renato Zannon
Renato Zannon

Reputation: 29941

Not directly related to your question, but since you mentioned "getters and setters" on your title, I thought I might complement the answers with ES5 getters and setters:

function Person(age, name) {
  this.name = name;
  this.age  = age;
};

Object.defineProperty(Person.prototype, "age", {
  get: function() {
    return this._age;
  },

  // Added a few things to demonstrate additional logic on the setter
  set: function(num) {
    num = parseInt(num, 10);
    if(num > 0) {
      this._age = num;
    }
  }
});

Then, it can be used transparently, as if it was a normal property:

var person = new Person(20, "Jane Doe");
person.age; // => 20

person.age = 15;
person.age; // => 15

person.age = "20";
person.age; // => 20 (number)

person.age = -2;
person.age; // => 20

Works on any recent browser, and IE >= 9.

Upvotes: 5

Daniel A. White
Daniel A. White

Reputation: 190897

You will have to store it as a public property on your instance. The commonly used convention is to use _ as denoting as a private member.

Here is an implementation for you.

function Person(age, name) {
    this.age(age);
}
Person.prototype.age = function (num) {
    if (!num) {
        return this._age;
    }
    else {
        this._age = num;
    }
}

Upvotes: 2

Related Questions