JavaScript:使用JSON实例化类

3

我有一个类 "House",如下:

class House{
    constructor(params){
       this.clear();
       // this = {...params} // I know that don't work !!!
       //--
       // if(params.address !== undefined) this.address = {...params.address}
       //...
    }

    clear(){
      this.address = {
         number: null,
         street: null,
         zipcode: null,
         ton: null,
      }
      this.access = {
         doorcode: null,
         stair: null,
      }
    }
}

我想创建一个 House 实例,并在构造函数中注入多个 JSON,如下所示:
const h = new House({address: { /* json */ }, access: { /* json */});

或者只有一个,像这样:

const h = new House({access: { /* json */});

在构造函数中,我是否必须检查“params”中的所有值以插入到正确的属性(嵌套对象)中?

我想避免创建其他类,如地址和访问,在house构造函数中创建每个实例的新实例。最佳实践是什么?

谢谢!


2
Object.assign(this,params)会起作用吗? - Sebastian Speitel
3个回答

2
使用 constructor 中的 Object.assign()对象解构 以及 默认参数,你可以很容易地实现这一点:

class House {
  static get defaultAddress () {
    return {
      number: null,
      street: null,
      zipcode: null,
      town: null
    }
  }

  static get defaultAccess () {
    return {
      doorcode: null,
      stair: null
    }
  }

  constructor({ address = House.defaultAddress, access = House.defaultAccess } = {}) {
    this.clear()
    Object.assign(this.address, address)
    Object.assign(this.access, access)
  }

  clear () {
    const { defaultAddress, defaultAccess } = House

    Object.assign(this, { address: defaultAddress, access: defaultAccess })
  }
}

// no object
console.log(new House())
// empty object
console.log(new House({}))
// partial object
console.log(new House({ address: { number: 1, street: 'street', zipcode: 12345, town: 'town' } }))
// empty sub-objects
console.log(new House({ address: {}, access: {} }))
// partial sub-objects
console.log(new House({ address: { number: 1, street: 'street' }, access: { doorcode: 321 } }))
// complete object
console.log(new House({ address: { number: 1, street: 'street', zipcode: 12345, town: 'town' }, access: { doorcode: 321, stair: 3 } }))
.as-console-wrapper{min-height:100%!important}


好的,但不仅限于特定的键。我会将其与下面的答案混合。谢谢。 - Brice Chaponneau

1
你可以循环遍历参数并手动设置它们。然后,要清除它们,删除所有自身属性(即非继承属性)。
class House {
  constructor(params) {
    // set data
    Object.assign(this, params);
  }

  clear() {
    for (let key in this) {
      if (this.hasOwnProperty(key))
        this[key] = undefined;  // or `delete this[key];`
    }
  }
}

let house = new House({type: "normal", height: 40});
console.log(house, house instanceof House);

当然,您可能希望将输入键限制为预定义的集合。您可以将这些键存储在静态类变量中,并使用它们循环访问constructorclear中的属性。

class House {
  constructor(params) {
    // check for invalid properties
    Object.keys(params).forEach(key => {
      if (!House.keys.includes(key)) 
        throw `Invalid paramater ${key}`;
    });
    // set data
    Object.assign(this, params);
  }

  clear() {
    for (let key in House.keys) {
      if (this.hasOwnProperty(key))
        this[key] = undefined;  // or `delete this[key];`
    }
  }
}
House.keys = ['type', 'height'];

let house = new House({type: 'normal', height: 40});
console.log(house, house instanceof House);

let error = new House({helloWorld: true});


我认为限制属性的最佳方法是将其与先前的答案混合。谢谢。 - Brice Chaponneau

0

我认为你想要一个通用的命名空间来存储实例属性 - 类似于React的props模式 - 你还可以为每个创建的实例指定默认值:

const defaultProps = { address: {}, access: {} };

class House {
  constructor(props = {}) {
    this.props = {...defaultProps, ...props};
  }
  clear() {
    this.props = {...defaultProps};
  }
}

你如何从另一个文件中导出所有内容? - Brice Chaponneau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接