Reputation: 1946
Is it possible to create a ES6 class, that assigns a default value to a property if it's not passed in the new method?
class myClass {
constructor(options) {
this.a = typeof options.a !== 'undefined' ? options.a : 'default a value';
this.b = typeof options.b !== 'undefined' ? options.b : 'default b value';
this.c = typeof options.c !== 'undefined' ? options.c : 'default c value';
}
}
var myClassWithValue = new myClass({a:'a value', b: 'b value'});
If I try to do this with this code, compiling with babeljs, I get a TypeError: Cannot set property 'c' of undefined.
Maybe I am not getting how classes work in javascript.
Upvotes: 38
Views: 72074
Reputation: 1
class myClass {
constructor(
a = 'default a value',
b = 'default b value',
c = 'default c value'
) {
this.a = a;
this.b = b;
this.c = c;
}
}
let myClassWithValue = new myClass('a value','b value');
console.log(myClassWithValue);
Upvotes: 0
Reputation: 169
I propose this solution with OR
operator, this seems more readable and easy to maintain, no need to define default value for option
variable.
class myClass {
constructor(options) {
this.a = options.a || 'default a value';
this.b = options.b || 'default b value';
this.c = options.c || 'default c value';
}
}
var v = new myClass({
a: 'a new value',
b: 'b new value'
});
// to test
console.log(v);
Upvotes: 1
Reputation: 1
I build this. I think it is the easiest way to read the code in this problem.
class myClass {
constructor(options){
let default_values ={
a: '',
b: '',
c: ''
}
options = {...default_values, ...options}
this.a = options.a;
this.b = options.b;
this.c = options.c;
}
}
Upvotes: -1
Reputation: 31
I made a small correction: Replaced the large object with Object()
class SomeClass {
constructor({a = 'defA', b = 'defB', c = 'defC'} = Object()) {
this.a = a;
this.b = b;
this.c = c; }
}
console.log(new SomeClass ({a:'a', b:'b', c:'c'}))
console.log(new SomeClass ({a:'a', c:'c'}))
(Node REPL) Output:
SomeClass { a: 'a', b: 'b', c: 'c' }
SomeClass { a: 'a', b: 'defB', c: 'c' }
Upvotes: 0
Reputation: 1492
If you would like to have some properties default but some not you can use also use spread operator (work as same as Object.assign answer)
const defaults = {someDefault: true};
class SomeClass {
constructor(config) {
this.config = {...defaults, ...config};
}
}
Upvotes: 9
Reputation: 1683
if there is no parameter passing through the constructor, it is assigned a default value as it was pre-set, I hope I have helped!
class User {
constructor(fullName = "fooName", lastName, canAccess = false) {
this.fullName = fullName;
this.lastName = lastName;
this.canAccess = canAccess;
}
}
Upvotes: 6
Reputation: 17
So I've been reading to the answers to this question and I haven't found one that works easily with extended classes, so I came up with this.
First you create a function that checks if an object has the properties of another object:
function checkValues(values = {}, targets) {
values = Object.keys(values);
targets = Object.keys(targets);
return values.every(keyValor => targets.includes(keyValor));
}
Then in a class you define the default values like this:
class Error {
constructor(options = {}) {
//Define default values
var values = {
title: '',
status: 500,
mesagge: ''
};
//Check if options has properties of values
var valid = checkValues(values, options);
//If options doesn't has all the properties of values, assign default values to options
if (!valid) {
options = valores
}
//Asign options to the class
Object.assign(this, options);
}
}
So now, if you want to have a child class you just need to declare the default values for that child class:
class FormError extends Error{
constructor (options = {}){
var values = {
invalidParams: [{name:'', reason: ''}]
};
var valid = checkValues(values, options);
if (!valid) { options = values}
super(options);
Object.assign(this, options);
}
}
EXAMPLE:
var a = new Error();
var b = new FormError();
var c = new FormError({invalidParams: [{name: 'User', reason: 'It has to be a string!'}]});
console.log(a, b, c);
Note: It only works if you want to have ALL the defaults values and not just some of them, for example:
var e = new Error({message: 'This is an error'});
console.log(e.message);// ''
//Error e will only have the default values, and message would be empty.
var h = new FormError({title: 'FORM ERROR', status: 400});
console.log(h.title);//''
//Error h will only have the defaults because I didn't provide 'invalidParams'
Upvotes: 0
Reputation: 3577
I'd just add it to the prototype. ES6 classes are just syntactic sugar, so you can use all the standard prototypal inheritance techniques that were available before the introduction of the class
keyword.
const {assign, seal} = Object;
class MyClass {
constructor(options) {
assign(seal(this), options);
}
}
assign(MyClass.prototype, {
a: "default a value",
b: "default b value",
c: "default c value"
});
Upvotes: 0
Reputation: 1049
Shorter and cleaner version based on Default parameters from MDN web docs.
class myClass {
constructor(
a = 'default a value',
b = 'default b value',
c = 'default c value'
) {
this.a = a;
this.b = b;
this.c = c;
}
}
let myClassWithValue = new myClass('a value','b value');
console.log(myClassWithValue);
With passing an Object.
class myClass {
constructor({
a = 'default a value',
b = 'default b value',
c = 'default c value'
}) {
this.a = a;
this.b = b;
this.c = c;
}
}
let options = {
a: 'a value',
b: 'b value'
}
let myClassWithValue = new myClass(options);
console.log(myClassWithValue);
Upvotes: 4
Reputation: 8539
Object.assign works for me as well
class RenderProperties {
constructor(options = {}){
Object.assign(this, {
fill : false,
fillStyle : 'rgba(0, 255, 0, 0.5)',
lineWidth : 1,
strokeStyle : '#00FF00'
}, options);
}
}
Upvotes: 33
Reputation: 41
I just asked a similar question and found this question after I came up with a solution, so I thought I'd post it here as well.
My question was specific to ES6 and using deconstruction to setting up parameter defaults for a class. It seems the spec doesn't allow you to directly deconstruct arguments unless you do something similar to what @Jaromanda X did.
I wanted something shorter and cleaner, and ended up using the following pattern:
class Test {
constructor(options) {
let {
defaultOne : defaultOne = 'default one value',
defaultTwo : defaultTwo = 'default two value',
defaultThree : defaultThree = 'default three value'
} = (options) ? options:{};
this.defaultOne = defaultOne;
this.defaultTwo = defaultTwo;
this.defaultThree = defaultThree;
this.init();
}
init() {
console.log(this.defaultOne);
console.log(this.defaultTwo);
console.log(this.defaultThree);
}
}
new Test({defaultOne: 'Override default one value'});
new Test();
All we're doing here is deconstructing the options argument, and we handle the undefined use case with a ternary.
Upvotes: 0
Reputation: 1
If you're going to use ES6, why not use all of ES6, i.e. default values for parameters and destructuring assignment
class myClass {
constructor({a = 'default a value', b = 'default b value', c = 'default c value'} = {a:'default option a', b:'default option b', c:'default option c'}) {
this.a = a;
this.b = b;
this.c = c;
}
}
var v = new myClass({a:'a value', b: 'b value'});
console.log(v.toSource());
var w = new myClass();
console.log(w.toSource());
http://www.es6fiddle.net/ibxq6qcx/
edit: also tested and confirmed to run on https://babeljs.io/repl/
Upvotes: 49
Reputation: 549
I would suggest the following:
class myClass {
constructor(options) {
const defaults = {
a: 'default a value',
b: 'default b value',
c: 'default c value'
};
const populated = Object.assign(defaults, options);
for (const key in populated) {
if (populated.hasOwnProperty(key)) {
this[key] = populated[key];
}
}
}
}
var myClassWithValue = new myClass({a:'a value', b: 'b value'});
Upvotes: 6