JavaScript 문자열을 멋지게 꾸며보세요

JavaScript의 새로운 기능은 Template Literal 입니다. 기본적으로 물건을 보간하고 줄 바꿈을 사용할 수 있는 멋진 문자열입니다. 그러나 템플릿 리터럴에는 잘 알려지지 않은 또 다른 기능이 있습니다. 아마도 약간 이상하고 사용 사례를 찾기 어렵기 때문일 것입니다.

그 기능은 "태그가 지정된"템플릿입니다. 아래에서는 태그가 지정된 템플릿에 대해 내가 가장 좋아하는 사용 사례를 강조합니다. 문자열이 코드를 보기 흉하게 만드는 것을 방지하는 것입니다.

줄 바꿈 긴 문자열



모든 사람은 코드의 각 행에 표시되는 문자 수를 제한해야 한다고 말합니다. 이 keep-it-short 지시어는 한 종류의 데이터, 특히 문자열에 대한 문제입니다. 단일 문자열 리터럴은 그 자체로 80자보다 길 수 있으며 그 길이를 리팩토링할 수 없습니다.

그래서 당신은 무엇을합니까?

고전적인 솔루션은 다음과 같습니다.

const myString = "Oh how I wish " +
  "that this string was shorter " +
  "so that I didn't have to break " +
  "it up like this. I mean seriously " +
  "look how hard it is to read! " +
  "and edit!"


끔찍하다.

이것은 태그가 지정된 템플릿으로 극적으로 개선할 수 있는 것입니다. 저는 oneline라는 태그를 만들었습니다. 이 태그를 사용하면 줄 바꿈과 들여쓰기를 원하는 만큼 사용할 수 있지만 여전히 한 줄 문자열로 끝납니다! (oneline 코드는 이 기사의 하단을 참조하십시오.)

const myString = oneline`
  When you console log this it will just
  be one long line. It looks like a bunch.
  But it's just one.
  I can even ident the rows.
  I could have started the first
  line right after that first tick,
  and can put the final tick on its
  own line or at the end of this one.
  `;


그 문자열은 줄 바꿈과 탭이 많은 것처럼 보이지만 실제로는 그렇지 않습니다. 당신이 보는 것은 태그가 지정된 템플릿으로 얻는 것이 아닙니다. 여기서 실제로 얻는 것은 myString 추가 공백이나 줄 바꿈이 없는 하나의 긴 문자열이라는 것입니다.

여러 줄 문자열로 코드 들여쓰기 일치



코드의 문자열에는 또 다른 일반적인 문제가 있습니다. 바로 여러 줄 문자열의 들여쓰기입니다. 템플릿 리터럴을 사용하면 (\n 를 명시적으로 입력하지 않고도) 문자열에 줄바꿈을 넣을 수 있으므로 개행 및 들여쓰기를 처리하기 위한 두 가지 옵션이 제공됩니다.

const myString = "Title\n" +
  "  Indented line 1\n" +
  "  Indented line 2\n  Indented Line 3\n";

const myString = `Title
  Indented Line 1
  Indented Line 2
  Indented Line 3
`;


이 템플릿 리터럴은 전혀 나쁘지 않아 보입니다. 하지만 지금은 어떻습니까?

function myFunction(){
  let myString;
  if(someCondition){
    if(someOtherCondition){
      myString = `Title
  Indented Line 1
  Indented Line 2
  Indented Line 3
`;
    }
  }
}


역겨운. 템플릿 리터럴은 입력된 그대로 공백을 사용하기 때문에 여러 줄 문자열은 컨텍스트에서 코드의 들여쓰기를 따를 수 없습니다. 즉, 태그가 지정된 템플릿을 사용하지 않는 한. 코드 컨텍스트의 들여쓰기를 준수하면서 여러 줄 문자열을 작성할 수 있는 undent라는 태그를 만들었습니다. 불필요한 들여 쓰기를 제거하기 때문에 "undent"라고 부릅니다. (undent 코드는 이 기사의 하단을 참조하십시오.)

// Same *result* as before, but allowing indentation to match the code.
function myFunction(){
  let myString;
  if(someCondition){
    if(someOtherCondition){
      myString = undent`
        Title
          Indented Line 1
          Indented Line 2
          Indented Line 3
        `;
    }
  }
}


작동 방식



템플릿 태그는 템플릿 리터럴의 내용을 일련의 문자열과 보간된 값으로 수신하는 일반적인 이전 함수입니다. 이것들을 함께 꿰매면 전체 문자열을 얻을 수 있습니다. 태그 기능을 사용하면 원하는 경우 모든 것을 함께 꿰매기 전에 작업을 수행할 수 있습니다.

코드는 다음과 같습니다(Typescript 내):

/** @file https://github.com/bscotch/node-util/blob/main/src/lib/strings.ts **/

/**
 * Concatenate the string fragments and interpolated values
 * to get a single string.
 */
function populateTemplate(strings:TemplateStringsArray,...interps:string[]){
  let string = '';
  for(let i = 0; i<strings.length; i++){
    string += `${strings[i]||''}${interps[i]||''}`;
  }
  return string;
}

/**
 * Shift all lines left by the *smallest* indentation level,
 * and remove initial newline and all trailing spaces.
 */
export function undent(strings:TemplateStringsArray,...interps:string[]){
  let string = populateTemplate(strings,...interps);
  // Remove initial and final newlines
  string = string
    .replace(/^[\r\n]+/,'')
    .replace(/\s+$/,'');
  const dents = string.match(/^([ \t])*/gm);
  if(!dents || dents.length==0){
    return string;
  }
  dents.sort((dent1,dent2)=>dent1.length-dent2.length);
  const minDent = dents[0];
  if(!minDent){
    // Then min indentation is 0, no change needed
    return string;
  }
  const dedented = string.replace(new RegExp(`^${minDent}`,'gm'),'');
  return dedented;
}

/**
 * Remove linebreaks and extra spacing in a template string.
 */
export function oneline(strings:TemplateStringsArray,...interps:string[]){
  return populateTemplate(strings,...interps)
    .replace(/^\s+/,'')
    .replace(/\s+$/,'')
    .replace(/\s+/g,' ');
}


대부분의 프로젝트에서 사용하는 이 템플릿 태그를 a node utility module에 포함했습니다. 이것이 바로 시도해 볼 수 있는 빠른 방법입니다.

태그가 지정된 템플릿에 대해 가장 좋아하는 사용 사례에 대해 듣고 싶습니다!

DevChat newsletter에 가입하여 이와 같은 추가 정보와 기업가 정신 및 gamedev에 대한 토론을 얻으십시오.

좋은 웹페이지 즐겨찾기