最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to supply default values to ES6 class properties? - Stack Overflow

programmeradmin0浏览0评论

I have a JavaScript class I would like to supply with default values using an object. I only want the default values to be part of the class if user input is not otherwise supplied for some of the values. However, I am not sure how to implement this. Here is my class:

// Class definition, properties, and methods
class iTunesClient {
  constructor(options) {
    this.term = options.terms;
    this.country = options.country;
    this.media = options.media;
    this.entity = options.entity;
    this.attribute = options.attribute;
    this.callback = options.callback;
    this.limit = options.limit;
    this.lang = options.lang;
    this.version = options.version;
    this.explicit = options.explicit;
    this.url = options.url;
  }
}

Here are my default values:

// Default values defined according to iTunes API
const defaults = {
  terms: 'default',
  country: 'US',
  media: 'all',
  entity: '',
  attribute: '',
  callback: '',
  limit: 50,
  lang: 'en-us',
  version: 2,
  explicit: 'yes',
  url: '',
};

I realize this is possible through default parameters for functions, but I would rather supply an object containing the default values.

I have a JavaScript class I would like to supply with default values using an object. I only want the default values to be part of the class if user input is not otherwise supplied for some of the values. However, I am not sure how to implement this. Here is my class:

// Class definition, properties, and methods
class iTunesClient {
  constructor(options) {
    this.term = options.terms;
    this.country = options.country;
    this.media = options.media;
    this.entity = options.entity;
    this.attribute = options.attribute;
    this.callback = options.callback;
    this.limit = options.limit;
    this.lang = options.lang;
    this.version = options.version;
    this.explicit = options.explicit;
    this.url = options.url;
  }
}

Here are my default values:

// Default values defined according to iTunes API
const defaults = {
  terms: 'default',
  country: 'US',
  media: 'all',
  entity: '',
  attribute: '',
  callback: '',
  limit: 50,
  lang: 'en-us',
  version: 2,
  explicit: 'yes',
  url: '',
};

I realize this is possible through default parameters for functions, but I would rather supply an object containing the default values.

Share Improve this question edited Oct 2, 2017 at 13:58 Doug Wilhelm asked Sep 29, 2017 at 20:08 Doug WilhelmDoug Wilhelm 7969 silver badges27 bronze badges 3
  • What is the issue with code at Question? – guest271314 Commented Sep 29, 2017 at 20:10
  • Usually, you would use Object.assign() to merge your default options with the passed in options into a new object and then use that to assign all your values with. – jfriend00 Commented Sep 29, 2017 at 20:10
  • Possible duplicate of How can I merge properties of two JavaScript objects dynamically? – gautsch Commented Sep 29, 2017 at 20:19
Add a ment  | 

4 Answers 4

Reset to default 8

A typical way to do this is to use Object.assign() to merge passed-in values with default values:

// Class definition, properties, and methods
class iTunesClient {
  constructor(options) {

    // Default values defined according to iTunes API
    const defaults = {
      terms: 'default',
      country: 'US',
      media: 'all',
      entity: '',
      attribute: '',
      callback: '',
      limit: 50,
      lang: 'en-us',
      version: 2,
      explicit: 'yes',
      url: '',
    };      

    let opts = Object.assign({}, defaults, options);
    this.term = opts.terms;
    this.country = opts.country;
    this.media = opts.media;
    this.entity = opts.entity;
    this.attribute = opts.attribute;
    this.callback = opts.callback;
    this.limit = opts.limit;
    this.lang = opts.lang;
    this.version = opts.version;
    this.explicit = opts.explicit;
    this.url = opts.url;
  }
}

To explain how Object.assign() works here:

  1. It starts with {} as a target (an empty object)
  2. Then it copies all the defaults into the empty object
  3. Then it copies all the passed in properties into that same target
  4. Then it returns the target object which you use for initializing all your instance data

Of course, if your instance property names are the same as the ones in your options object, you could do this in a more DRY fashion like this:

// Class definition, properties, and methods
class iTunesClient {
  constructor(options) {

    // Default values defined according to iTunes API
    const defaults = {
      terms: 'default',
      country: 'US',
      media: 'all',
      entity: '',
      attribute: '',
      callback: '',
      limit: 50,
      lang: 'en-us',
      version: 2,
      explicit: 'yes',
      url: '',
    };      

    let opts = Object.assign({}, defaults, options);

    // assign options to instance data (using only property names contained
    //  in defaults object to avoid copying properties we don't want)
    Object.keys(defaults).forEach(prop => {
        this[prop] = opts[prop];
    });
  }
}

You could do it like this:

class iTunesClient {
  constructor(options) {

    // Default values defined according to iTunes API
    const defaults = {
      terms: 'default',
      country: 'US',
      media: 'all',
      entity: '',
      attribute: '',
      callback: '',
      limit: 50,
      lang: 'en-us',
      version: 2,
      explicit: 'yes',
      url: '',
    };      

    this.term = opts.terms || defaults.terms;
    this.country = opts.country || defaults.country;
    this.media = opts.media || defaults.media;
    this.entity = opts.entity || defaults.entity;
    this.attribute = opts.attribute || defaults.attribute;
    this.callback = opts.callback || defaults.callback;
    this.limit = opts.limit || defaults.limit;
    this.lang = opts.lang || defaults.lang;
    this.version = opts.version || defaults.version;
    this.explicit = opts.explicit || defaults.explicit;
    this.url = opts.url || defaults.url;
  }
}

But you have to be wary of 'falsy' values, e.g. if opts.limit is passed in as 0 then this.limit will be set to defaults.limit value, even though opt was defined.

I think the better solutions for that, stackoverflow./a/48775304/10325885

class User {
    constructor(options = {}) {
        this.name = options.name || "Joe";
        this.age = options.age || 47;
    }
}

I think is much cleaner to read, if you just use ||.

For something a little more modern than the examples above you can use destructuring and default parameters.

class iTunesClient {
  constructor({
    term = '',
    country = 'US',
    media = 'all',
    entity = '',
    attribute = '',
    callback = '',
    limit = 50,
    lang = 'en-us,
    version = 2,
    explicit = 'yes',
    url = '',
  }) {
    this.term = terms;
    this.country = country;
    this.media = media;
    this.entity = entity;
    this.attribute = attribute;
    this.callback = callback;
    this.limit = limit;
    this.lang = lang;
    this.version = version;
    this.explicit = explicit;
    this.url = url;
  }
}

That way any params that are not part of the constructor object will get set to the default. You can even pass an empty object and just get all defaults.

发布评论

评论列表(0)

  1. 暂无评论