스무싱 자바스크립트

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

JavaScript 개발자로서 smoosh-gate에 대해 들어본 적이 있을 것입니다. JavaScript의 언어 동작을 정의하는 ECMAScript 표준 설계를 담당하는 일부 TC39 사람들은 rename flatten ~ smooshflatMap ~ 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과 같은 일부 약속 라이브러리에는 별도의 mapflatMap 메서드가 제공되지만 대부분 then를 사용하고 여기에서 병합에 대해 크게 신경 쓰지 않습니다.

배열에서 이 문제에 대한 해결책은 flattenflatMap 메서드를 배열에 추가하는 것이었습니다. 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를 추가하여 newArrayelement로 줄입니다. 이 배열이 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과 별개로 내장 버전과 함께 제공된다면 좋을 것입니다.

좋은 웹페이지 즐겨찾기