Archive

RxJS Operator (계속 업데이트)

|

[RxJS] Operator (계속 업데이트)


1. Operator

연산자는 함수이다. 연산자에는 2종류가 있다.

  • 파이프형 연산자 : pipe(operator()) 구문을 사용해서 input에 대한 같은 output만을 반환하는 순수연산을 한다. 따라서, 파이프형 연산자는 순수함수이고 Observable 객체를 받아 다른 Observable을 반환한다.

    pipe() : 파이프 연산자는 RxJS 5.5 이전에 사용되던 chaining을 가독성 좋게 사용할 수 있게 해준다.

    // Before RxJS 5.5
    Observable.operator1().operator2().operator3().subscribe(...);
    
    // Since RxJS 5.5
    Observable.pipe(
    	operator1(),
        operator2(),
        operator3()
    ).subscribe(...);
    


  • 생성 연산자 : 새로운 Observable 객체를 생성하기 위해 단독 함수로서 호출될 수 있다.


2. Higher-order Observables (고차 Observables)

Observable은 보편적으로 string, number 같은 보통의 값을 내보내지만, observable을 다루는 observable을 고차 Observable이라고 한다.

고차 Observable은 일반적으로 평탄화해서 사용하는데 고차 Observable을 하나의 보통 Observable로 바꿔서 사용한다.

concatAll(), mergeAll(), switchAll(), exhaust(), concatMap(), mergeMap(), switchMap(), exhaustMap() 등 사용.


3. Marble Diagram (마블 다이어그램)

Observable의 연산자를 설명할 때 시간의 흐름에 따라 어떻게 작동하는지 그림을 통해 시각적으로 제공한다.

Marble Diagram : https://rxmarbles.com/


4. Custom Operator

pipe() 함수로 새로운 연산자를 만들 수 있다. 흔히 사용되는 연산자들의 시퀀스를 하나로 묶을 수 있다.

import { pipe } from "rxjs";
import { filter, map } from "rxjs/operators";

function discardOddDoubleEven() {
  return pipe(
    filter((v) => !(v % 2)),
    map((v) => v + v)
  );
}
// 홀수를 버리고 짝수를 2배하는 Custom Operator

pipe() 함수는 Observable의 pipe() 메소드와 유사하지만 같지 않다.


5. 자주 사용되는 연산자 정리

👻 Creation Operators

of() : 나열된 인자를 순서대로 next하는 Observable 반환

import { of } from "rxjs";

of(1, 2, 3).subscribe(
  (next) => console.log("next: ", next),
  (err) => console.log("err: ", err),
  () => console.log("complete")
);
// next: 1, next: 2, next: 3, complete

// 배열을 전달하면 배열이 통으로 나옴
of([1, 2, 3]).subscribe(
  (next) => console.log("next: ", next),
  (err) => console.log("err: ", err),
  () => console.log("complete")
);
// next: [1,2,3], complete


from() : array, observable, Promise, string, array-like, iterable 등을 Observable로 반환

import { from } from "rxjs";

const arr = [1, 2, 3];
const result = from(arr);
result.subscribe((x) => console.log(x));
// 1, 2, 3


fromEvent() : 브라우저에서 발생하는 Event를 Observable로 반환

import { fromEvent } from "rxjs";

const clicks = fromEvent(document, "click");
clicks.subscribe((x) => console.log(x));
// MouseEvent Object


defer() : 팩토리 함수로 Observable 생성 후 구독 시점에 팩토리 함수를 호출해 만들어둔 Observable 반환받아 구독한다. from은 Promise 생성 후 바로 동작시키지만 defer는 Observable을 subscribe하는 시점에 Promise를 생성할 수 있어서 동작 시점을 조절할 수 있다.

import { defer, fromEvent, interval } from "rxjs";

const clickOrInterval = defer(() => {
  return Math.random() > 0.5 ? fromEvent(document, "click") : interval(1000);
});
clickOrInterval.subscribe((x) => console.log(x));

// 랜덤 숫자가 0.5보다 크면 클릭 이벤트를 대기한다.
// 랜덤 숫자가 0.5보다 작으면 1초마다 방출한다.


range() : 범위 내 숫자들을 갖는 Observable 생성

import { range } from "rxjs";

const numbers = range(1, 10);
numbers.subscribe((x) => console.log(x));
// 1부터 10까지 출력


interval() : setInterval()과 유사하며 일정 간격마다 값을 발행하는데 0부터 순차적으로 증가, 명시적으로 구독해제 하지 않으면 무한하게 값을 발행하니 주의할 것.

import { interval } from "rxjs";

const intervalObservable = interval(1000).subscribe(
  (v) => console.log("next: ", v),
  (err) => console.log("err: ", err),
  () => console.log("complete")
);

setTimeout(() => {
  intervalObservable.unsubscribe();
}, 3000);

// next: 1, next: 2, next: 3, complete


timer() : setTimeout()과 유사하며 특정 시간 이후 값을 발행한다.

import { timer } from "rxjs";

const numbers = timer(3000, 1000); // 3초 후에 시작하며 1초마다 발행
numbers.subscribe((x) => console.log(x));

setTimeout(() => {
  numbers.unsubscribe();
}, 6000);

// 0, 1, 2


empty(), never(), throwError() : empty()는 Observable complete 상태를 전달하는 Observable 생성, never()는 어떤값도 발행하지 않는 Observable, throwError()는 호출 즉시 에러를 발생시킨다. empty()와 never()는 RxJS 6 이후 deprecated되었으며 상수로 변경되었다.

import { EMPTY } from "rxjs";

EMPTY.subscribe(
  () => console.log("next"),
  (err) => console.log("err"),
  () => console.log("complete")
);
// complete

import { NEVER } from "rxjs";

NEVER.subscribe(
  () => console.log("next"),
  (err) => console.log("err"),
  () => console.log("complete")
);
// 아무것도 출력되지 않음

import { throwError } from "rxjs";

throwError("err!").subscribe(
  () => console.log("next"),
  (err) => console.log("err: ", err),
  () => console.log("complete")
);
// err: err!


👻 Transformation Operators

map() : array method의 map과 유사하며 Observable을 다른 Observable로 변환하는데 사용된다.

const observable = of(1, 2, 3, 4, 5);

const subscription = observable
  .pipe(map((val) => val * val))
  .subscribe((val) => console.log(val));
// 1, 4, 9, 16, 25


mapTo() : Observable이 값을 방출할 때마다 주어진 상수 값을 방출한다.

import { fromEvent } from "rxjs";
import { mapTo } from "rxjs/operators";

const clicks = fromEvent(document, "click");
const greetings = clicks.pipe(mapTo("Foo"));
greetings.subscribe((x) => console.log(x));

// click시마다 'Foo' 출력


mergeMap() : Observable이 방출하는 값을 출력 Observable과 함께 병합한다.

import { of, interval } from "rxjs";
import { mergeMap, map } from "rxjs/operators";

const letters = of("a", "b");
const result = letters.pipe(
  mergeMap((x) => interval(1000).pipe(map((i) => x + i)))
);
result.subscribe((x) => console.log(x));

// a0, b0, a1, b1, a2, b2 ...


switchMap() : mergeMap과 비슷하지만, 외부 Observable이 발생될 때마다 내부 Observable의 새로운 구독이 시작된다.

import { fromEvent, interval } from "rxjs";
import { switchMap } from "rxjs/operators";

const clicks = fromEvent(document, "click");
const result = clicks.pipe(switchMap((ev) => interval(1000)));
result.subscribe((x) => console.log(x));

// click, 0, 1, 2, click, 0, 1, click, 0 ...
// 클릭할 때마다 구독이 취소되고 새로운 구독이 시작됨


👻 Filtering Operators

debounceTime() : 출력 사이의 지정된 시간이 경과하지 않으면 이 시간 내의 방출된 값들을 버린다.

import { fromEvent } from "rxjs";
import { debounceTime } from "rxjs/operators";

const clicks = fromEvent(document, "click");
const result = clicks.pipe(debounceTime(3000));
result.subscribe((x) => console.log(x));

// 마지막 클릭 후 3초 후에 click object 출력


throttleTime() : 지정된 시간동안 처음 값을 제외한 값들을 버린다.

import { fromEvent } from "rxjs";
import { throttleTime } from "rxjs/operators";

const clicks = fromEvent(document, "click");
const result = clicks.pipe(throttleTime(3000));
result.subscribe((x) => console.log(x));

// 클릭 연타 시 처음 click Object 출력 후 3초 후에 click Object 출력


take() : take(number)의 number에 전달된 값과 같은 개수의 값들만 방출한다.

filter() : array method의 filter와 유사하며 Observable의 필터링에 사용된다

const observable = of(1, 2, 3, 4, 5);

const subscription = observable
  .pipe(filter((val) => val % 2 === 0))
  .subscribe((val) => console.log(val));
// 2, 4


👻 Join Operators

startWith() : 출력 Observable이 방출되기 전에 startWith의 소스들이 먼저 방출된다.

import { of } from "rxjs";
import { startWith } from "rxjs/operators";

of("a", "b")
  .pipe(startWith("first", "second"))
  .subscribe((x) => console.log(x));

//  'first', 'second', 'a', 'b'


withLatestFrom() : 두 개의 Observable을 합성하지만, 한쪽에서 이벤트가 발생할 때에만 합성해준다. 이벤트 발생이 없다면 스킵된다.

import { fromEvent, interval } from "rxjs";
import { withLatestFrom } from "rxjs/operators";

const clicks = fromEvent(document, "click");
const timer = interval(1000);
const result = clicks.pipe(withLatestFrom(timer));
result.subscribe((x) => console.log(x));

// click이 발생할때만 [click Object, 경과한 시간]이 출력된다.


👻 Error Handling Operators

catchError() : 오류 발생 시 새 Observable을 반환하거나 오류를 반환하거나 retry 할 수 있다.

import { of } from "rxjs";
import { map, catchError } from "rxjs/operators";

of(1, 2, 3, 4, 5)
  .pipe(
    map((n) => {
      if (n === 4) {
        throw "four!";
      }
      return n;
    }),
    catchError((err) => of("I", "II", "III", "IV", "V"))
  )
  .subscribe((x) => console.log(x));
// 오류 발생 시 다른 Observable 방출
// 1, 2, 3, I, II, III, IV, V

import { of } from "rxjs";
import { map, catchError, take } from "rxjs/operators";

of(1, 2, 3, 4, 5)
  .pipe(
    map((n) => {
      if (n === 4) {
        throw "four!";
      }
      return n;
    }),
    catchError((err, caught) => caught),
    take(30)
  )
  .subscribe((x) => console.log(x));
// 오류 발생 시 retry한다
// 1, 2, 3, 1, 2, 3, ...

import { of } from "rxjs";
import { map, catchError } from "rxjs/operators";

of(1, 2, 3, 4, 5)
  .pipe(
    map((n) => {
      if (n === 4) {
        throw "four!";
      }
      return n;
    }),
    catchError((err) => {
      throw "error in source. Details: " + err;
    })
  )
  .subscribe(
    (x) => console.log(x),
    (err) => console.log(err)
  );
// 오류 발생 시 new error를 발생시킨다.
// 1, 2, 3, error in source. Details: four!


👻 Utility Operators

tap() : 소스에서 각 방출을 가로채서 함수를 실행하지만 오류가 발생하지 않는 한 소스와 동일한 출력을 반환

import { fromEvent } from "rxjs";
import { tap, map } from "rxjs/operators";

const clicks = fromEvent(document, "click");
const positions = clicks.pipe(
  tap((ev) => console.log(ev)),
  map((ev) => ev.clientX)
);
positions.subscribe((x) => console.log(x));


delay() : 주어진 시간까지 Observable 방출을 지연시킨다.

import { fromEvent } from "rxjs";
import { delay } from "rxjs/operators";

const clicks = fromEvent(document, "click");
const delayedClicks = clicks.pipe(delay(1000)); // 1초씩 지연되어 방출
delayedClicks.subscribe((x) => console.log(x));

// ---------------------------------------------------------------

import { fromEvent } from "rxjs";
import { delay } from "rxjs/operators";

const clicks = fromEvent(document, "click");
const date = new Date("March 15, 2050 12:00:00");
const delayedClicks = clicks.pipe(delay(date)); // 해당 날짜 후에 방출 가능
delayedClicks.subscribe((x) => console.log(x));



참고 자료


ReactiveX 공식문서

RxJS 공식문서

[Javascript] RxJS - Operators

redux-actions 사용하기

|

redux-actions 사용하기


1. redux-actions 왜 사용할까?

  • createAction을 통한 액션 생성 자동화

  • handleActions로 swtich문 대체

    기존 방식의 reducer로 scope를 설정하는 결점을 보완

2. 사용법

  • createAction
import {createAction} from 'redux-actions';

// 기존 액션 생성 방식
// export const increment = (index) => {
// 	type: 'INCREMENT',
//  payload: index
// };

// 1. createAction 사용
export const increment = createAction('INCREMENT');

increment(3); // { type: 'INCREMENT', payload: 3 }

// 2. parameter가 여럿일 때
export const updateColor = createAction('UPDATE_COLOR');
// action에 객체를 넣어서 parameter로 전달
updateColor({ index: 3, color: '#ffffff'});
// { type: 'UPDATE_COLOR', payload: { index: 3, color: '#ffffff' }};

// 3. parameter 명시
export const createUser = createAction('CREATE_USER', ({index, name}) => ({index, name}));

createUser({index: 1, name: 'foo'});


  • handleActions
import {handleActions} from 'redux-actions';

const reducer = handleActions({
    INCREMENT: (state, action) => ({
        counter: state.counter + action.payload
    })
}, { counter: 0 });

action을 매핑한 후 defaultState 설정



참고 자료


Ducks 구조와 redux-actions 사용하기

ReactJS - redux-actions를 이용한 더 쉬운 액션 관리

RxJS 개념정리 - 반응형 프로그래밍,Observable,Subject,Scheduler

|

[RxJS] 개념정리


1. RxJS란 무엇인가

RxJS는 ReactiveX의 Javascript를 위한 라이브러리이다.

ReactiveX는 Observer 패턴, Iterator 패턴, 함수형 프로그래밍을 조합하여 제공한다.

ReactiveX는 이벤트를 observable로 추상화하여 시간에 따른 스트림으로 간주할 수 있게 한다.

observable이 observer에게 전달되기 전, operator를 이용해 재가공이 가능하다.

RxJS를 사용해 비동기 코드를 직관적이고 가독성 좋게 작성할 수 있다.


2. 반응형 프로그래밍(Reactive Programming)

반응형 프로그래밍은 이벤트나 배열과 같은 데이터 스트림을 비동기로 처리해 변화에 유연하게 반응하는 프로그래밍 패러다임이다.

반응형 프로그래밍은 외부에서 명령하지 않고, 응답이 오면 그때그때 반응하여 처리하는 Push 시나리오를 채택하고 있으며, 데이터를 가져오기 위해서는 subscribe해야한다.

Vanilar JS에서 이벤트를 처리하는 방식인 addEventListener가 이와 같은 방식이다.

targetElement가 이벤트를 subscribe하고 이벤트가 발생하면 event function이 작동한다.

여기서 Observer 패턴을 볼 수 있다.

Observer pattern은 객체의 상태 변화를 관찰하는 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다.

addEventListener로 이벤트를 구독하는 옵저버를 등록하고 이벤트 발생 시 event function을 호출하여 옵저버에게 알리는 방식이다.

하지만, 이 event function이 외부 변수를 참조하고 있다면 순수성을 잃고 side-effect가 발생할 수도 있다.

이를 RxJs로 처리하면 다음과 같이 순수함수로 작성할 수 있다.

import {fromEvent} from 'rxjs';
import {scan} from 'rxjs/operators';

fromEvent(document, 'click')
 .pipe(scan(count => count + 1, 0))
 .subscribe(console.log(`${count}번 클릭!`));


3. Observable

Observable은 시간의 흐름에 따라 발생하는 이벤트들의 스트림이라고 볼 수 있다.

pipeline을 설치하여 여러 이벤트나 데이터를 Observer에게 보낸다.

스트림은 관념적으로 뒤에 $를 붙인다.

Observable.create()new Observable()로 생성할 수 있다.

생성 연산자를 사용한 Observable 생성은 추후 정리하겠다.

Observable의 subscribe()를 통해 Observer 객체를 생성하고 만들어진 Observer 객체로

함수를 호출해 값을 발행한다.

Observable을 subscribe하고 반환받은 객체로 구독을 해제할 수 있다.

const subscription = observable.subscribe(x => console.log(x));
subscription.unsubscribe();

Observable의 unsubscribe()로 구독을 해제하면 Observable을 실행하지 않고 멈춘다.

Observer는 next, error, complete 3가지 함수로 구성된 객체이다.

  • next : Observable subscriber에게 데이터를 전달한다
  • complete : Observable subscriber에게 완료를 알리면 next가 데이터 전달을 멈춘다.
  • error : Observable subscriber에게 에러를 전달하면 next, complete가 발생하지 않는다.

Observable은 생성, 구독, 실행, 구독해제의 Life-Cycle을 가진다.

  1. 생성 : Observable.create()
  2. 구독 : Observable.subscribe()
  3. 실행 : observer.next()
  4. 구독해제 : observer.complete() / Observable.unsubscribe()


4. Subject

Subject는 멀티캐스팅을 지원하는 객체이다.

일반적으로 하나의 Observable에 하나의 Observer를 등록하지만,

Subject는 여러 Observer를 생성하고 데이터를 전달받을 수 있다.

Subject는 Observable이면서 Observer이기도 하다.

따라서 여러 Observable을 구독할 수 있고 next,error,complete 함수를 호출할 수 있다.

const subject = new Subject();
subject.subscribe({
    next: (x) => console.log(`observer A : ${x}`)
});
subject.subscribe({
    next: (x) => console.log(`observer B : ${x}`)
});
subject.next(1);
subject.next(2);

/*
observer A : 1
observer B : 1

observer A : 2
observer B : 2
*/


5. Scheduler

Javascript는 싱글 스레드, 이벤트 루프로 동작하지만 RxJs의 Scheduler를 사용하여

이벤트 루프에 스케쥴링이 가능하다

  1. asyncScheduler : setTimeout과 비슷
  2. asapScheduler : 다음 이벤트 루프 실행
  3. queueScheduler : 스케쥴러에 전달된 state를 처리



참고 자료


ReactiveX 공식문서

RxJS 공식문서

RxJS의 이해와 사용

RxJS 간단정리

React에서 classnames 활용하기

|

React에서 classnames 활용하기


classnames 패키지를 이용하여 className을 dynamic하게 관리할 수 있다.

key-value로 설정하여 value의 true/false 평가에 따른 조건부 className 적용이 가능하다.

import classNames from 'classnames';

function Button (props) {
    const { isLoading } = props;
    return {
        <button className={classNames('btn', {'btn-loading': isLoading})}></button>
    }
}

이런 식으로 isLoading이 undefined가 아니고 true일 때, dynamic하게 클래스명을 조건부로 설정할 수 있다.



참고 자료


classnames - npm

Lodash 총정리 (계속 업데이트)

|

Lodash 총정리 (계속 업데이트)


1. array

  • chunk() : 길이에 맞춰 배열 분리, 길이 안맞으면 마지막에 붙임
_.chunk([1,2,3,4,5], 3); // [[1,2,3], [4,5]]
  • compact() : false 값을 제거한 배열을 만듦
_.compact([0,1,false,2,'',3,undefined,4]); // [1,2,3,4]
  • difference() : 첫번째 배열에서 나머지 배열들에 없는 값만 새로운 배열로 반환. sameValueZero를 사용하여 동등비교 ※sameValueZero : === 와 비슷한데 NaN를 비교했을 때, true가 나온다는 점이 다름.
_.difference([1,2], [2,3], ["1", "2"]); // [1]
  • drop() : 첫번째부터 n개의 요소가 삭제된 배열 반환, default = 1
_.drop([1,2,3,4], 3); // [4]
  • fill() : 배열의 요소를 값으로 채움, 몇번째부터 몇번째까지 지정 가능
_.fill([1,2,3], 2); // [2,2,2]
_.fill([1,2,3,4], '*', 1, 3); // [1,*,*,4];
  • findIndex() : find()와 비슷하나, 찾은 첫번째 요소의 인덱스를 반환한다는 점이 다름
const a = [
    { 'name': 'rabbit', 'active': false },
    { 'name': 'monkey', 'active': true },
    { 'name': 'dog', 'active': false }
]

_.findIndex(a, function(e){ return e.name === 'dog' }); // 2, 콜백 결과가 처음 true인 값
_.findIndex(a, ['active', true]); // 1, 해당 key와 value를 가진 값
_.findIndex(a, 'active'); // 1, 해당 key를 가지고 value가 처음 true인 값
  • head() : 배열의 첫번째 요소 반환, 비어있으면 undefined 반환, 반대는 last()
_.head([1,2,3]); // 1
_.head([]); // undefined
  • flatten() : single level deep로 병합
_.flatten(1, [2, [3]], [4,[5,[6]]]); // [1,2,[3],4,[5,[6]]]
  • flattenDeep() : 깊은 병합
_.flattenDeep(1, [2, [3]], [4,[5,[6]]]); // [1,2,3,4,5,6]
  • fromPairs() : key-value Object로 반환
_.fromPairs([['a', 1], ['b', 2]]); // { 'a': 1, 'b': 2}
  • initial() : 배열의 마지막 요소 제외한 배열 반환
_.initial([1,2,3]); // [1,2]
  • intersection() : difference()와는 반대로 겹치는 요소 배열 반환
_.intersection([3,4], [4,5]); // [4]
  • nth() : 배열의 n번째 요소를 반환
_.nth([1,2,3], 2); // 3
_.nth([1,2,3], -2); // 2
  • pull() : sameValueZero를 이용하여 지정된 모든 요소를 제거
_.pull(['a', 'b', 'c', 'a', 'c'], 'a', 'c'); // ['b']
  • pullAt() : 인덱스에 해당하는 요소를 제거하고 반환, 새배열 x
const array = ['a', 'b', 'c', 'd'];
const pulled = _.pullAt(array, [1, 3]); // ['b', 'd'];
console.log(array); ['a', 'c'];
  • remove() : 조건식이 true인 요소를 배열에서 제거 후 반환, 새배열x
const array = [1,2,3,4];
const removed = _.remove(array, function(e){ return e % 2 === 0 }); // [2,4]
console.log(array); // [1,3]
  • tail() : 배열의 첫번째 요소를 제외한 모든 요소 반환
_.tail([1,2,3]); // [2,3]
  • take() : 배열 시작부터 n개의 요소를 모아서 반환, default = 1, 배열 길이보다 넘기면 전부 반환
_.take([1,2,3]); // [1]
_.take([1,2,3], 2); // [1,2]
_.take([1,2,3], 4); // [1,2,3]
_.take([1,2,3], 0); // []
  • union() : sameValueZero로 동일성 비교하여 순서대로 고유한 값의 배열 반환
_.union([2], [1,2], [2,3]); // [2,1,3];
  • uniq() : sameValueZero로 동일성 비교하여 중복없는 배열 반환
_.uniq([2,3,2,1,3,1]); // [2,3,1]
  • without() : sameValueZero로 동일성 비교하여 주어진 값을 제외한 배열 반환
_.without([2,3,1,3,2], 2, 3); // [1]


2. Lang

  • castArray() : 배열이 아닌 경우 배열로 캐스팅
_.castArrray('abc'); // ['abc']
  • clone() : 얕은 복사
const object = [{a:1},{b:2}];
const shallow = _.clone(object);
shallow[0].a = 100;
console.log(object[0].a); // 100
console.log(shallow[0].a); // 100
  • cloneDeep() : 깊은 복사
const object = [{a:1},{b:2}];
const shallow = _.cloneDeep(object);
shallow[0].a = 100;
console.log(object[0].a); // 1
console.log(shallow[0].a); // 100
  • conformsTo() : object의 속성이 특정 조건을 준수하는지 확인
const object = { a:1, b:2 };
_.conformsTo(object, { b: function(e) { return e > 1 }}); // true
_.conformsTo(object, { b: function(e) { return e > 3 }}); // false
  • eq() : sameValueZero로 동등비교하여 동일한지 확인
const obj1 = { 'a': 1};
const obj2 = { 'a': 1};

_.eq(obj1, obj2); // false
_.eq(NaN, NaN); // true
  • gt() : 값이 다른 값보다 큰지 확인, 반대 lt()
_.gt(3,1); // true
_.gt(3,3); // false
_.gt(1,3); // false
  • gte() : 값이 다른 값보다 크거나 같은지 확인, 반대 lte()
_.gte(3,1); // true
_.gte(3,3); // true
_.gte(1,3); // false
  • isArray() : array인지확인
_.isArray([1,2,3]); // true
_.isArray('123'); // false
  • isBoolean() : boolean인지 확인
_.isBoolean(false); // true
_.isBoolean([false]); // false
  • isDate() : Date 객체인지 확인
_.isDate(new Date()); // true
_.isDate('Mon April 23 2021'); // false
  • isElement() : DOM element인지 확인
_.isElement(document.body); // true
_.isElement('<body>'); // false
  • isEmpty() : 객체, 배열이 비어있는지 확인
_.isEmpty(null); // true
_.isEmpty([1]); // false
_.isEmpty({a:1}); // false
  • isEqual() : 두 값을 deep 비교하여 동일한지 확인
const obj1 = {a:1};
const obj2 = {a:1};

_.isEqual(obj1, obj2); // true
obj1 === obj2; // false
  • isError() : Error 객체인지 확인
_.isError(new Error); // true
  • isFinite() : 유한한 숫자인지 확인
_.isFinite(3); // true
_.isFinite(Infinity); // false
  • isFunction() : function 객체인지 확인
_.isFunction(function(){}); // true
  • isInteger() : integer인지 확인
_.isInteger(3); // true
_.isInteger(Number.MIN_VALUE); // false
  • isMatch() : 객체를 심층비교하여 동일한 속성이 포함되어 있는지 확인
const obj = {a:1, b:2};
_.isMatch(obj, {b:2}); // true
_.isMatch(obj, {b:1}); // false
  • isNaN() : NaN인지 확인
_.isNaN(3); // false
_.isNaN(NaN); // true
_.isNaN(undefined); // false
isNaN(undefined); // true
  • isNil() : null인지 undefined인지 확인
_.isNil(null); // true
_.isNil(undefined); // true
_.isNil([]); // false
  • isNull() : null인지 확인
_.isNull(null); // true
_.isNull(undefined); // false
  • isObject() : object인지 확인
_.isObject({}); // true
_.isObject([1,2,3]); // true
  • isSafeInteger() : 안전한 정수인지 확인
_.isSafeInteger(3); // true
_.isSafeInteger(Number.MIN_VALUE); // false
  • isString() : String인지 확인
_.isString('a'); // true
_.isString(1); // false
  • isUndefined() : undefined인지 확인
_.isUndefined(null); // false
_.isUndefined(undefined); // true
  • isPlainObject() : 값이 일반 객체인지, 생성자에 의해 생성된 객체인지 확인
_.isPlainObject(new Date()); // false
_.isPlainObject([1,2,3]); // false
_.isPlainObject({a:1}); // true
  • toArray() : array로 변환
_.toArray({a:1, b:2}); // [1,2]
_.toArray('abc'); // ['a', 'b', 'c']
_.toArray(1); // []
  • toFinite() : 값을 유한한 숫자로 변환
_.toFinite(Number.MIN_VALUE); // 5e-324
  • toInteger() : 값을 integer로 변환
_.toInteger(Number.MIN_VALUE); // 0
_.toInteger(3.2); // 3
_.toInteger('3,2'); // 3
  • toString() : 문자열로 변환
_.toString(null); // ''
_.toString([1,2,3]); '1,2,3'
  • toNumber() : 숫자로 변환
_.toNumber(3.2); // 3.2
_.toNumber('3.2'); // 3.2
_.toNumber(Infinity); // Infinity


3. Object

  • assign() : 왼쪽에서 오른쪽으로 합치는데 중복되는 값은 오른쪽 기준.
_.assign({a:1},{a:2, b:3},{b:4, c:5}); // {a: 2, b: 4, c: 5}
  • defaults() : 첫번째 객체에 나머지들 병합, 중복된 키값은 무시
_.defaults({a:1}, {b:2}, {a:3}); // {a:1, b:2}
  • defaultsDeep() : 첫번째 객체에 나머지들 깊은 병합
_.defaultsDeep({a: {b:2}}, {a: {b:3, c:4}}); // {a: {b:2, c:4}}
  • has() : 값이 객체의 속성인지 확인
const obj = {a: {b: 2}};
_.has(obj, 'a'); // true
  • values() : 객체에서 value 값만 추출한 배열을 반환
_.values({a:1, b:2, c: [3,4]}); // [1, 2, [3,4]]
_.values('asd'); // ['a', 's', 'd']
  • get() : 객체의 해당 key에 대한 value를 가져옴, 옵션으로 default value 설정 가능
const obj = {a:1, b:2, c: {d: 4}};
_.get(obj, 'a'); // 1
_.get(obj, 'z'); // undefined
_.get(obj, 'z', 4); // 4
_.get(obj, 'c.d'); // 4
  • merge() : 객체 병합, deep merge가 가능함
const A1 = {
    B: {
        C: 'C1',
      	E: 'E'
    }
}

const A2 = {
    B: {
      	C: 'C2'
        D: 'D',
    }
}
_.merge(A1, A2); // { B: { C: 'C2', E: 'E', D: 'D'}}
// 중복된 key 값에 대해서 오른쪽 순서로 적용된 것을 볼 수 있다
  • create() :
  • omit() : 객체에서 해당 key를 제외한 객체 반환
const obj = {a:1, b:2, c:3};
_.omit(obj, ['a', 'c']); // {b:2}
_.omit(obj, 'a'); // {b:2, c:3}
  • pick() : 객체에서 선택한 key로 구성된 객체 반환
const obj = {a:1, b:2, c:3};
_.pick(obj, ['a', 'c']); // {a:1, c:3}
  • transform() :
  • result() : function의 경우 부모 객체의 this 바인딩으로 호출되고 결과를 반환, 그 외엔 get()과 동일



참고 자료


lodash - 공식문서