Reputation: 385
I have this code for a class that receives some parameters, and I'm assigning them as object properties once each time.
class InitAnimation {
constructor(settingsAnimation, settingButton, isHelp, isEnd) {
// Initialized the configuration for main animation.
this.settingsAnimation = settingsAnimation;
this.settingButton = settingButton;
this.yes = null;
this.no = null;
this.isHelp = isHelp;
this.isEnd = isEnd;
this.initConfig();
}
Is there a cleaner way to do this in ES6, in which I just can take the arguments key-values and assign them to the object as computed property names? Something like:
class InitAnimation {
constructor(settingsAnimation, settingButton, isHelp, isEnd) {
// Initialized the configuration for main animation.
// I know this doesn't work on 'arguments'
arguments.forEach(key => this[key] = arguments[key]);
this.initConfig();
}
For this case I can't modify the way parameters are sent because that would imply changing everyone else's code and the project is kinda big right now. Can I do this in a better way without changing how parameters are passed?
Upvotes: 2
Views: 2811
Reputation: 91
Given constructor options are wrapped in an object, which I personally prefer not to mess up the arguments order:
const pet = new Feline({breed, age, sex})
you can easily assign them inside the class:
class Feline {
constructor(args) {
Object.assign(this, args)
}
...
}
Typescript and intellisence will likely hate it, but in an environment without TS it's quick and dirty fix to pass as much stuff as you need inside a class.
Upvotes: 0
Reputation: 222474
There are several options here.
Object literal can be used to assign properties. This results in copying and pasting parameters in order to enumerate them explicitly but results in more solid code and function signature that can be statically analyzed:
constructor(foo, bar) {
Object.assign(this, { foo, bar });
...
}
Arguments can be processed according to parameter list. This results in parameter list that is enumerated once, but function signature is loose, it cannot be statically analyzed and is prone to human errors:
constructor(...args) {
['foo', 'bar']
.forEach((paramName, i) => {
this[paramName] = args[i];
});
}
It should be noticed that this is efficiently solved in TypeScript with parameter properties and is one of the reasons why it can be chosen over vanilla JavaScript:
constructor(public foo) {}
is syntactic sugar for
constructor(foo) {
this.foo = foo;
}
Upvotes: 3
Reputation: 5188
You can detect the names of a function's arguments using this technique:
https://davidwalsh.name/javascript-arguments
So you could apply that to your constructor, then use a loop to match up the argument names with their values (by index) and then apply them to an object.
function argumentsToObject( func, args ) {
const argNames = getArgumentNames( func ); //use the code from the above link to do this
const resultObject = {};
argsNames.forEach( ( argName, index ) => {
var argValue = args[index];
resultObject[ argName ] = argValue;
});
}
Then in your constructor, do
const argsObject = argumentsToObject( InitAnimation.prototype.constructor, arguments );
//copy all the arguments onto this
Object.assign( this, argsObject );
Upvotes: 1
Reputation: 1074295
Yes, in ES2015+ you can use Object.assign
and shorthand properties:
constructor(settingsAnimation, settingButton, isHelp, isEnd) {
// Initialized the configuration for main animation.
Object.assign(this, {settingsAnimation, settingButton, isHelp, isEnd});
this.yes = null;
this.no = null;
this.initConfig();
}
Live Example:
class InitAnimation {
constructor(settingsAnimation, settingButton, isHelp, isEnd) {
// Initialized the configuration for main animation.
Object.assign(this, {settingsAnimation, settingButton, isHelp, isEnd});
this.yes = null;
this.no = null;
this.initConfig();
}
initConfig() {
}
}
const a = new InitAnimation("a", "b", "c", "d");
console.log(a);
Upvotes: 5