1

I've been playing with JavaScript dynamic formatting today and I can't seem to get this to work and wondered if anyone out there has done the same.

This is my function I've created to pass in a set number of formatters in for, say, strings, numbers etc:

function Formatter(formatters) { this.format = function(value, type) { switch(type) { case "string": return value => formatters.string break; case "currency": return value => formatters.curency break; case "number": return value => formatters.number break; default: return value; break; } } } 

I'm sending to it in the initialisation this:

formatters: { 'string': input => input, 'number': input => input.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,'), 'currency': input => input.toFixed(3), 'url': input => (`<a href="${input.url}">${input.title}</a>`) } 

Soo...

var formatter = new Formatter({ 'string': input => input, 'number': input => input.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,'), 'currency': input => input.toFixed(3), 'url': input => (`<a href="${input.url}">${input.title}</a>`) }); // This should display "test" as the format is just itself. formatter.format("test", "string); 

What it actually displays is value => formatters.string.

Is there any way to achieve what I'm trying to do here?

2
  • there is no formatters.value Commented Jul 29, 2017 at 20:16
  • Took me a bit, but I figured it out! Commented Jul 30, 2017 at 3:45

2 Answers 2

3

@jhpratt points what's the error.

I just wanted to suggest you should't use classes at all. Never.

This solution has much less code noise. Readable, maintainable

const formatters = { 'string': input => input, 'number': input => input.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,'), 'currency': input => input.toFixed(3), 'url': input => (`<a href="${input.url}">${input.title}</a>`) } const format = (type, value) => formatters[type](value) const formatted = format('string', 'hello') console.log(formatted)

UPDATE

Using curry to pass formatters as well

const formatters = { 'string': input => input, 'number': input => input.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,'), 'currency': input => input.toFixed(3), 'url': input => (`<a href="${input.url}">${input.title}</a>`) } const format = formatters => type => value => formatters[type](value) // You can use it in one call format(formatters)('string')('hello') // Create a function with predefined formatters const myFormatter = format(formatters) myFormatter('string')('hello') // Create a function with predefined formatters and for a specific type const urlFormatter = format(formatters)('url') urlFormatter('https://www.google.com')

Sign up to request clarification or add additional context in comments.

5 Comments

Yes, but what if you want different formatting options (as in two formatters)? Then you'll be polluting the namespace with format and formatters multiple times. Using a class only uses one name, not two.
With class you have to instantiate another class either way which gives another name. So one instead of two for exchange for readability, maintainability and reusability worth for me. Or you can pass formatters as well as a function argument with using curry for example.
This is brilliant, and I'm torn on choosing an answer here as @jhpratt originally guided the problem and this expands upon that one. I'll upvote this as it's great, but have to accept the other answer as it's taken a lot of time to figure out. I'm very greatful to you both.
Regarding his comments, I understand what he's saying, but it's just that you can ignore the variable for the formatter as it's encapsulated in the class. Ultimately I would say it depends on how many formatters you're using.
I just wanted to point out that trying to use class inheritance and classes in general in javascript is a bad practice. I also used to use it, but after you forget 'class', 'new' and 'this' in js your life becomes easier and also the other developers' who read your code. If you are interested I can recommend these series from Kyle Simpson: github.com/getify/You-Dont-Know-JS, github.com/getify/Functional-Light-JS and also reading posts from Eric Elliott on medium.com, like this series: medium.com/javascript-scene/…
2

Ok, so basically what you're doing is returning the arrow function itself, rather than the called value. What you'll want to do is call formatters.string with a paremeter value.

function Formatter(formatters) { this.format = function(value, type) { switch(type) { case "string": return formatters.string(value); break; case "currency": return formatters.curency(value); break; case "number": return formatters.number(value); break; default: return value; break; } }; } var formatter = new Formatter({ 'string': input => input, 'number': input => input.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,'), 'currency': input => input.toFixed(3), 'url': input => ('<a href="${input.url}">${input.title}</a>') }); // This should display "test" as the format is just itself. formatter.format("test", "string"); 

2 Comments

Just a side note, JavaScript (ES6) has native classes, which you might want to check out.
Thank you for your time here, I know it was a difficult question and time consuming to figure out. Very much appreciated!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.