스무싱 자바스크립트

12003 단어 javascriptcoding
Cover image by David on Flickr, cropped by me.

JavaScript 개발자로서 smoosh-gate에 대해 들어본 적이 있을 것입니다. JavaScript의 언어 동작을 정의하는 ECMAScript 표준 설계를 담당하는 일부 TC39 사람들은 rename flatten ~ smoosh 및 flatMap ~ smooshMap 에 대한 아이디어를 가지고 있었습니다. MooTools를 사용하는 일부 웹사이트는 그렇지 않으면 중단될 수 있기 때문입니다. 이러한 방법은 현재 proposal이며 표준의 일부가 아닙니다.

어쨌든, 나는 MooTools나 표준에 대해 잘 모르지만, 이 기능들이 정확히 무엇을 하는지 설명하고 싶었습니다.

왜



대부분의 경우 JavaScript를 프로그래밍할 때 가장 좋아하는 펑터, 배열 및 약속을 어지럽힐 것입니다. 때때로 그것들은 중첩되지만 당신은 이것에 대해 신경 쓰지 않습니다. 숫자 배열이 아니라 숫자 배열이 필요하거나 JSON 결과에 대한 약속이 아닌 서버의 JSON 결과가 필요합니다.

뭐



프라미스는 이미 중첩된 프라미스를 평면화하는 then 메서드와 함께 제공됩니다.

// loadDataA returns a promise
const dataAPromise = loadDataA();

// dataAPromise resolves to a result with an id that is used to load the next data
// loadDataB returns a promise too
const dataBPromise = dataAPromise.then(result => loadDataB(result.id))

// dataBPromise resolves to the resulting data
// and not the the promise returned from the callback above.
// It's flattened out right away so you only care about the result
const upperCasePromise = dataBPromise.then(result => result.someText.toUpperCase())

// upperCasePromise resolves to the upper case text
// returned by the previous callback.
upperCasePromise.then(upperCaseText => console.log(upperCaseText));


그래서 여기에서 할 일이별로 없습니다. Bluebird과 같은 일부 약속 라이브러리에는 별도의 map 및 flatMap 메서드가 제공되지만 대부분 then를 사용하고 여기에서 병합에 대해 크게 신경 쓰지 않습니다.

배열에서 이 문제에 대한 해결책은 flatten 및 flatMap 메서드를 배열에 추가하는 것이었습니다. flatten 메서드는 배열의 모든 중첩된 배열을 해당 중첩된 요소의 내용으로 바꾸고 빈 요소도 제거합니다.

이 함수는 reduce 의 도움으로 수동으로 작성할 수 있습니다.

const flatten = a => a.reduce(
  (newArray, element) =>
    element instanceof Array
      ? [...newArray, ...element]
      : element !== undefined? [...newArray, element] : newArray,
  []
);

const a = [1, [2, 3, 4], , 5];
flatten(a); // -> [1, 2, 3, 4, 5]


모든 a를 추가하여 newArray를 element로 줄입니다. 이 배열이 istanceof Array인 경우 해당 element의 모든 요소를 ​​newArray에 추가합니다. (... -operator는 기존 배열에 추가하는 대신 두 경우 모두에 대해 새 배열을 생성하지만 요점은 알 것 같습니다.

명령형 버전은 다음과 같을 수 있습니다.

function flatten(a) {
  let b = [];
  for (let element of a) {
    if (element instanceof Array) {
      for (let subElement of element) {
        b.push(subElement);
      }
    } else if (element !== undefined) {
      b.push(element);
    }
  }
  return b;
}

const a = [1, [2, 3, 4], , 5];
flatten(a); // -> [1, 2, 3, 4, 5]


이것의 flatMap 버전은 flatten 에 의해 생성된 새 배열에서 단순히 map 를 호출합니다.

const flatMap = (f, a) => flatten(a.map(f));

const a = [1,0,7,-3];
flatMap(x => x != 0? 1/x : undefined, a);
// -> [1, 0.14285714285714285, -0.3333333333333333]

const c = [1,2,5];
flatMap(x => ''.padEnd(x, ".").split(""), c);
// -> [".", ".", ".", ".", ".", ".", ".", "."]


실제 구현은 아마도 함수가 아닌 메서드처럼 작동할 것입니다.

// Instead of 
flatten(a.map(x => [1,x]));

// it would be
a.map(x => [1,x]).flatten();

// instead of
flatMap(x => [1,x], a);

// it would be
a.flatMap(x => [1,x]);


결론



Flatten은 모든 프로그램에서 여러 번 수행되는 다소 중요한 작업이므로 JavaScript가 최종 이름인 lol과 별개로 내장 버전과 함께 제공된다면 좋을 것입니다.

좋은 웹페이지 즐겨찾기