한줄 지식

한줄로 끝나는 지식들을 잠시 모아둔다. 추후에 더 많은 내용을 알게된다면 글로도 쓸 수 있는 내용들이다.

일반 이메일 정규식

RFC 5322에 의거한 공식적인 기준이다.

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

recursion vs reentrancy

재귀(recursion)와 재진입(reentrancy)의 차이는 자바스크립트에서도 존재한다. 재귀 함수는 재진입해야 하지만, 모든 재진입이 재귀적인 것은 아니다.

재귀(recursion) 함수

자기 자신을 호출하는 함수이다.

function foo(shouldRecurse) {
  console.log("foo start");
  if (shouldRecurse) {
    foo(false);
  }
  console.log("foo stop");
}
foo(true);

재진입(reentrancy)

재귀가 아닌 재진입의 예이다.

function foo(fn) {
  console.log("foo start");
  fn();
  console.log("foo stop");
}
function bar() {
  console.log("bar");
  foo(baz);
}
function baz() {
  console.log("baz");
}
foo(bar);

재귀를 이용한 deepcopy

deepcopy를 하는 방법은 여러가지가 존재하지만, 아래와 같은 방법은 json에서 지원되지 않는 포맷은 마음대로 캐스팅해버리기 때문에 개발자가 의도하지 않은 부수 효과가 발생할 수 있다.

JSON.parse(JSON.stringify(items));

따라서 lodashclonedeep을 사용하거나 아래와 같은 재귀 함수를 이용하여 문제를 해결 할 수 있다.

function deepcopy(items) {
  return items.map((item) => (Array.isArray(item) ? deepcopy(item) : item));
}

크롬설정

크롬 브라우저에서 ES2016+ 기능 활성화하기

chrome://flags/#enable-javascript-harmony // enabled!


ES6(ES2015)+

spread, rest operators

ES5에서는 배열을 함수의 파라미터로 바꿔주기 위해 apply() 함수를 사용했었다. ES6에서는 스프레드 연산자를 통해 이를 대체할 수 있다.

const params = [1, 2, 3];
// ES5
console.log(sum.apply(undefined, params));

// ES6
console.log(sum(...params));

또한 스프레드 연산자를 통해 rest arguments를 나타낼 수 있다.

function sum(x, y, ...args) {
  // or You can write 'function sum(...args) ...'.
  return x + y + args.reduce((pre, cur) => pre + cur, 0);
}

console.log(sum(1, 2), sum(1, 2, 3, 4), sum(1, 2, 3, 4, 5)); // 3 10 15

array destructuring

const [name, age] = ["jacob", 30];
console.log({ name, age }); // {name: 'jacob', age: 30}

이 문법은 값을 스왑할때 유용하게 사용할 수 있다:

(x = "jacob"), (y = 30);
[y, x] = [x, y];
console.log({ x, y }); // {x: 30, y: 'jacob'}

Exponentiation operator

기존의 Math.pow 메서드를 대체할 수 있으며, ES7의 지수 연산자를 통해 더 쉬운 계산이 가능하다.

const area = 3.14 * r * r;

// Math.pow
const area = 3.14 * Math.pow(r, 2);

// **
const area = 3.14 * r ** 2;

피보나치 수열

어떤 수열의 항이, 항의 두 항의 합과 같은 수열을 말한다.

const fibonacci = [];
fibonacci[1] = 1;
fibonacci[2] = 1;

// 피보나치 수열의 처음 20개의 숫자를 찾는 경우
for (let i = 3; i < 20; i++) {
  fibonacci[i] = fibonacci[i - 1] + fibonacci[i - 2];
}
// (20) [empty, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,
// 233, 377, 610, 987, 1597, 2584, 4181]

Array method

entries() vs values()

entries의 경우 value에 포지션 값도 value 배열의 첫번째 값으로 같이 반환하는데 비해, values는 값만 반환해 준다.

const arr = [1, 2, 3, 4, 5];

arr.entries().next(); // {value: [0, 1], done: false}
arr.values().next(); // {value: 1, done: false}

Array.from() vs Array.of()

Array.from() 메서드의 경우 기존 배열을 새 배열로 복사하며, Array.of() 메서드의 경우 메서드에 전달된 인수를 가지고 새 배열을 만든다.

const arr = [1, 2, 3, 4, 5];

const newArray1 = Array.from(arr);
const newArray2 = Array.of(...arr); // or Array.of(1,2,3,4,5)

console.log({ newArray1, newArray2 }); // {newArray1: [1,2,3,4,5], newArray2: [1,2,3,4,5]}

Promise의 장점 (콜백에 비해)

  1. 프라미스 기반의 함수 및 메서드의 타입 시그니처가 더 명확하다. 예를 들어 함수가 콜백 기반이라면 일부 매개변수는 인풋(input)에 관한 것이고 끝에 있는 한 개 이상의 콜백 함수는 아웃풋(output)에 관한 것이지만, 프라미스를 이용하면 아웃풋(output)과 관련된 모든 것은 반환된 값을 통해 처리된다.

  2. 비동기 처리 단계를 체이닝(chaining)하는 것이 더 편리하다.

  3. 프라미스는 동기 오류와 비동기 오류를 모두 처리한다(.catch()). 반면 비동기를 위해 콜백함수를 사용하면, 일반적으로 예외 처리가 되지 않으며, 개발자가 스스로 해야한다.

  4. 프라미스는 단일 표준이다.

null vs undefined

  • undefined: 초기화 되지 않았거나 존재하지 않음을 의미한다.

  • null: 객체의 값의 의도적 부재를 의미한다. (ecma262)

structuredClone

node 17에서의 DeepCopy를 가능하게 해주는 메서드이다. 2021년 1월 기준 현재 LTS 버전이 16이기 때문에 별로 만날 일은 없을 확률이 크지만, 딥카피에 대해 찾아보다가 재미있어 추가해 본다.

Last updated