使对象的所有属性可变

Make all properties of object mutable

本文关键字:属性 对象      更新时间:2023-09-26

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

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

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

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

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

设置
用作属性的 setter 的函数,如果没有 setter,则未定义。该函数将仅接收 参数 分配给属性的新值。默认为 定义。

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

@meagar的答案是正确的。

但是有一个更简单的方法:只需像往常一样分配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 />');