使对象的所有属性都可变

时间:2015-03-14 13:57:21

标签: javascript oop

如何定义对象的属性,因此如果其中一个被更改,则所有其他属性都会自动更新。

到目前为止,我已经提出了这个代码,但它不起作用:

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

因此,在创建新对象后,可以对其进行适当更改:

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

2 个答案:

答案 0 :(得分:3)

value不是动态计算的。随着对象的变化,它不会发生变化。为了动态计算属性,您需要使用get and set定义getter和setter:

  

获取
  一个函数,用作属性的getter,如果没有getter则不定义。函数返回将用作   财产的价值。默认为undefined。

     

设置
  用作属性的setter的函数,如果没有setter则为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




答案 1 :(得分:0)

@meagar's answer是正确的。

但是有一种更简单的方法:只需像往常一样分配firstNamelastName属性,然后只为fullName定义一个getter和setter:

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