简体   繁体   中英

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

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(/^[az]+ [az]+$/)) 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 

@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 />'); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM