patternjavascriptMinor
Add functionality to object then remove those functions on export
Viewed 0 times
thoseremoveexportthenfunctionsobjectfunctionalityadd
Problem
Outline
I have a form that needs validation. The problem is that the software requires custom validation that depends on multiple parameters.
I decided to pass the object into a function which will dynamically give the object the functions it needs to be validated.
Then once the validation is completed, I remove those functions from the object.
I'm adding the functions so I can chain them together, which I believe will provide me with great composition.
Usage
This is how I add the functions to the object:
I can then chain the added functions like this:
That way my functions are composable and reusable.
Implementation
Now for the actual code to be reviewed:
I'm forced to use the class because I need Aurelia Dependency Injection. I compose my functions outside of that
This code works perfectly, and it executes as expected; however, I do have a few concerns:
I have a form that needs validation. The problem is that the software requires custom validation that depends on multiple parameters.
I decided to pass the object into a function which will dynamically give the object the functions it needs to be validated.
Then once the validation is completed, I remove those functions from the object.
I'm adding the functions so I can chain them together, which I believe will provide me with great composition.
Usage
This is how I add the functions to the object:
let q = this.validator.validate(this.question)I can then chain the added functions like this:
q.validateString().cleanUp();That way my functions are composable and reusable.
Implementation
Now for the actual code to be reviewed:
export class Validator {
validate(question) {
let q = Object.assign(
{},
question,
validationOptions
);
return q;
}
}
let validationOptions = {
validateString,
cleanUp
};
function validateString() {
return this;
}
function cleanUp() {
Object.keys(validationOptions).map((i) => delete this[i]);
return this;
}I'm forced to use the class because I need Aurelia Dependency Injection. I compose my functions outside of that
class Validator because they only need to work with the this binding.This code works perfectly, and it executes as expected; however, I do have a few concerns:
- Is there a downside to the way I add these functions?
- The way I remove these functions works well, but are there better options? I can't use
Symbolbecause I return theq objectto another class.
Solution
Mild issue with assigning functions
It's possible that you could overwrite properties of a
When you execute
Alternative to deleting the functions
I think a better way to "delete" the added functions would be to just keep track of the original
That way the initial object is unchanged, and you don't have to concern yourself with deleting the validation functions from the question when your done.
Wrapper Class
I think you also ought to consider making the validator a wrapper class for your
If you want the validation functions to be free from an object, classes have prototypes that you can assign the methods to:
If you have a lot of functions you could do:
It's possible that you could overwrite properties of a
question if they have the same name as one of your validation functions. For example:let question = {
foo: "bar"
};
let validationOptions = {
foo,
cleanUp
};When you execute
Object.assign the later object's properties override earlier ones in the arguments array.Alternative to deleting the functions
I think a better way to "delete" the added functions would be to just keep track of the original
question object, and then return it from cleanUp:export class Validator {
validate(question) {
let q = Object.assign(
{},
question,
validationOptions
);
q.cleanUp = () => question;
return q;
}
}
let validationOptions = {
validateString
};
function validateString() {
// validate
return this;
}That way the initial object is unchanged, and you don't have to concern yourself with deleting the validation functions from the question when your done.
Wrapper Class
I think you also ought to consider making the validator a wrapper class for your
question. That way your validation functions stay out of your data, you can still chain your methods, and you don't have to assign the validation functions for each object:export class Validator {
constructor(question) {
this.data = question;
}
validateString() {
return this;
}
cleanUp() {
return this.data;
}
}If you want the validation functions to be free from an object, classes have prototypes that you can assign the methods to:
function validateString() {
return this;
}
export class Validator {
constructor(question) {
data = question;
}
}
Validator.prototype.validateString = validateString;If you have a lot of functions you could do:
let validateOptions = {
validateString,
validateDate,
validateAge
};
Object.keys(validateOptions).forEach((property) => {
Validator.prototype[property] = validateOptions[property];
});Code Snippets
let question = {
foo: "bar"
};
let validationOptions = {
foo,
cleanUp
};export class Validator {
validate(question) {
let q = Object.assign(
{},
question,
validationOptions
);
q.cleanUp = () => question;
return q;
}
}
let validationOptions = {
validateString
};
function validateString() {
// validate
return this;
}export class Validator {
constructor(question) {
this.data = question;
}
validateString() {
return this;
}
cleanUp() {
return this.data;
}
}function validateString() {
return this;
}
export class Validator {
constructor(question) {
data = question;
}
}
Validator.prototype.validateString = validateString;let validateOptions = {
validateString,
validateDate,
validateAge
};
Object.keys(validateOptions).forEach((property) => {
Validator.prototype[property] = validateOptions[property];
});Context
StackExchange Code Review Q#130091, answer score: 2
Revisions (0)
No revisions yet.