3
\$\begingroup\$

The code below transforms the text area's input to camelCase. I am wondering if this code is considered correct to write in terms of performance and readability and if not, what are your improvements?

This accepts only values with an underscore, use this test data in the text area: underscore_case first_name Some_Variable calculate_AGE delayed_departure

document.body.append(document.createElement('textarea'));
document.body.append(document.createElement('button'));
const text = document.querySelector('textarea');
const button = document.querySelector('button');
button.addEventListener('click', function () {
  if (!text.value.includes('_'))
    console.log(`The string doesnt contain an underscore.`);
  else {
    const val = text.value.toLowerCase().split(' ');
    const fixedNames = [];
    let i = 0;
    for (let word of val) {
      if (word.includes('_')) {
        i++;
        word = word.split('_');
        word[1] = word[1].slice(0, 1).toUpperCase() + word[1].slice(1);
        word = word.join('').padEnd(20, ' ') + `${'✔️'.repeat(i)}`;
        fixedNames.push(word);
      }
    }
    return console.log(fixedNames.join(`\n`));
  }
});

\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

Currently a lot of the string transform logic is mixed with the DOM handling code. Ideally, each function should only have a single responsibility - so let's fix that.

First, let's separate the camel casing code into a separate function:

function camelCase(word){
  halves = word.split('_');
  halves[1] = halves[1].slice(0, 1).toUpperCase() + halves[1].slice(1);
  return halves.join('')
}

Let's also clean up the transforming loop. I would rewrite it in a more functional style using .map and .filter instead of an explicit for loop:

function transformWords(words){
  return words
    .filter(word => word.includes('_'))
    .map((word, i) => camelCase(word).padEnd(20, ' ') + '✔️'.repeat(i + 1));
}

On to the DOM code. Instead of dynamically constructing elements using JS, define it statically in HTML.

<textarea id="transform-input"></textarea>
<button id="transform-button">Transform to Camel Case</button>

Now for the corresponding JS. Variable names were modified to clarify their content. I switched from document.querySelector to document.getElementById for a similar reason.

const transformInput = document.getElementById('transform-input');
const transformButton = document.getElementById('transform-button');

transformButton.addEventListener('click', function(){
  if (!text.value.includes('_')){
    console.log('The string doesn\'t contain an underscore.');
    return;
  }

  const words = text.value.toLowerCase().split(' ');

  const fixedNames = transformWords(words);
  console.log(fixedNames.join('\n'));
});

You also included a few unnecessary template strings throughout the code - if you don't need the extra functionality, just use a normal single (or double) quoted string.

Full Code:

const transformInput = document.getElementById('transform-input');
const transformButton = document.getElementById('transform-button');

transformButton.addEventListener('click', function(){
  if (!transformInput.value.includes('_')){
    console.log('The string doesn\'t contain an underscore.');
    return;
  }

  const words = transformInput.value.toLowerCase().split(' ');

  const fixedNames = transformWords(words);
  console.log(fixedNames.join('\n'));
});

function camelCase(word){
  halves = word.split('_');
  halves[1] = halves[1].slice(0, 1).toUpperCase() + halves[1].slice(1);
  return halves.join('')
}

function transformWords(words){
  return words
    .filter(word => word.includes('_'))
    .map((word, i) => camelCase(word).padEnd(20, ' ') + '✔️'.repeat(i + 1));
}
<textarea id="transform-input"></textarea>
<button id="transform-button">Transform to Camel Case</button>

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.