Clarity
Clarity

Reputation: 10873

Make all properties of object mutable

How do i define properties of an object, so if one of them is changed all other are automatically updated.

I have come up with this code so far, but it doesn't work:

function CreateNamed(first, last) {
    Object.defineProperties(this, {
           "firstName": {
            value: first,
            writable: true
        },
            "lastName": {
            value: last,
            writable: true
        },
            "fullName": {
            value: first + ' ' + last,
            writable: true
        }
    });
}

So after a new object is created it can be changed appropriately:

var b = new CreateNamed('Bill', 'Gates'); // Bill Gates
b.firstName = 'Paul'; // b.fullName = Paul Gates
b.lastName = 'Wood'; // b.fullname = Paul Wood
b.fullName = 'Chuck Norris' // b.firstName = Chuck, b.lastName = Norris

Upvotes: 1

Views: 1061

Answers (2)

Oriol
Oriol

Reputation: 288120

@meagar's answer is correct.

But there is a simpler approach: just assign the firstName and lastName properties as usual, and then only define a getter and setter for fullName:

function CreateNamed(first, last) {
  this.firstName = first;
  this.lastName = last;
  Object.defineProperty(this, "fullName", {
    get: function () { return this.firstName + ' ' + this.lastName },
    set: function (name) {
      name = name.split(' ');
      if(name.length != 2) throw new Error('I cannot parse that name');
      this.firstName = name[0];
      this.lastName = name[1];
    }
  });
}

function CreateNamed(first, last) {
  this.firstName = first;
  this.lastName = last;
  Object.defineProperty(this, "fullName", {
    get: function () { return this.firstName + ' ' + this.lastName },
    set: function (name) {
      name = name.split(' ');
      if(name.length != 2) throw new Error('I cannot parse that name');
      this.firstName = name[0];
      this.lastName = name[1];
    }
  });
}

var ouput = [];

var user = new CreateNamed('bob', 'smith');
ouput.push(user.fullName); // bob smith

user.firstName = "john"; 
ouput.push(user.fullName); // john smith

user.fullName = "tony brian";
ouput.push(user.firstName); // tony
ouput.push(user.lastName); // brian

document.body.innerHTML = ouput.join('<br />');

Upvotes: 0

user229044
user229044

Reputation: 239311

value is not computed dynamically. It won't change as the object changes. In order to dynamically compute properties, you need to define getters and setters using get and set:

get
A function which serves as a getter for the property, or undefined if there is no getter. The function return will be used as the value of property. Defaults to undefined.

set
A function which serves as a setter for the property, or undefined if there is no setter. The function will receive as only argument the new value being assigned to the property. Defaults to undefined.

function CreateNamed(first, last) {
    this.first = first;
    this.last = last;
    Object.defineProperties(this, {
           "firstName": {
           get: function() { return this.first; },
           set: function(name) { this.first = name; }
        },
            "lastName": {
           get: function() { return this.last; },
           set: function(name) { this.last = name; }
        },
            "fullName": {
            get: function () { return this.first + ' ' + this.last },
            set: function (name) {
              if (!name.match(/^[a-z]+ [a-z]+$/))
                throw new Error('I cannot parse that name')
              var parts = name.split(' ')
              this.first = parts[0];
              this.last = parts[1];
            }
        }
    });

}

var user = new CreateNamed('bob', 'smith');
document.write(user.fullName); // bob smith

user.firstName = "john"; 
document.write(user.fullName); // john smith

user.fullName = "tony brian";
document.write(user.firstName); // tony
document.write(user.lastName); // brian

Upvotes: 3

Related Questions