koans javascript 회고 (2/3)

김민아·2022년 7월 14일
post-thumbnail

koans javascript

koans, 결론을 내리기 전에 이게 왜 맞는지 깊게 고민한다.

Spread

배열을 풀어서 인자로 전달하거나, 배열을 풀어서 각각의 요소로 넣을 때에 사용한다. 특히 배열을 합치거나 복사할 때 유용하다. (slice()처럼)

const spread = [1, 2, 3];
const arr = [0, ...spread, 4];

console.log(arr) // [0, 1, 2, 3, 4]

객체도 사용할 수 있다.

const user = {
  name: 'mina',
  age: 4,
};

const userExtra = {
  status: 'busy',
};

const merged = { ...user, ...userExtra };

console.log(merged) // {name: 'mina', age: 4, status: 'busy'}

Rest

파라미터를 배열의 형태로 받아서 사용할 수 있다. 파라미터 개수가 가변적일 때 유용하다.

function getAllParamsByRestParameter(...args) {
  return args;
}

const restParams = getAllParamsByRestParameter('1', '2', '3');

consolelog(restParams) // ['1', '2', '3']

전달인자의 일부만 가져올 수도 있다. 나머지 ...rest는 배열로

function getAllParams(required1, required2, ...args) {
  return [required1, required2, args];
}

console.log(getAllParams(123)) // [123, undefined, []]

Object.assign()

Object.assign()은 속성의 값을 복사한다.

let copiedObj = Object.assign({}, obj);

빈 배열에 obj(있다고 가정)를 복사한다. 목표 객체({})의 속성 중 소스 객체(obj)와 동일한 키를 가지면, 소스 객체의 속성값으로 덮어쓴다. 소스 객체가 여러개일 경우 키가 겹치면, 뒤쪽 객체의 속성 값으로 교체된다. 목표 객체는 변경(mutable)된다.

let user = {
    name:'mina',
    age: 4,
    status: 'sleep'
}

let source1 = {
    name: 'JK',
    age: 10
}

let source2 = {
    status: 'play',
    age: 14,
    favorite: 'yellow'
}

Object.assign(user, source1, source2)

console.log(user) 
// {name: 'JK', age: 14, status: 'play', favorite: 'yellow'}

Shallow Copy & Deep Copy

중첩된 배열의 참조 관계

그림1처럼 생각하기 쉽지만, 그림2처럼 중첩된 배열 요소는 또 다른 heap에 저장된 주소를 참조하고 있다. 그래서 복사를 하더라도 중첩된 inner 배열은 여전히 같은 주소를 담게 된다. (얕은 복사)

모든 중첩된 참조 변수들을 실제 다른 주소값으로 전부 복사하는 것을 깊은 복사라고 하는데, 재귀함수를 사용하는 방법 등이 있다.

1

2


slice() - 배열

널리 알려진 방식으로 slice()가 있다. 다만, slice()는 중첩 구조 복사를 제대로 수행할 수 없다는 단점이 있다.

spread() - 배열, 객체

const fullPre = {
  duration: 4,
  mentor: 'hongsik',
};

const me = {
  status: 'sleepy',
  todos: ['coplit', 'koans'],
};

const merged = { ...fullPre, ...me };

fullPreme를 spread를 사용해 merged에 담았다(복사). mergedmentor를 바꾸면 fullPrementor는 변하지 않는다. (값 복사)

merged.mentor = 'mina'
console.log(fullPre.mentor) // 'hongsik'

merged.todos의 배열을 바꾸면 바뀐다. (얕은 복사)

merged.todos[0] = 'copy'
console.log(me.todos) // ['copy', 'koans']

Object.assign() - 객체

slice(), spread 문법, Object.assign()으로 배열혹은 객체를 복사할 때, 1 depth에서만 값이 복사(얕은 복사)되고 다차원 복사(깊은 복사)는 다른 방법을 써야한다!


arguments & array-like

arguments는 모든 함수의 실행 시 자동으로 생성되는 '객체'입니다.

function getAllParamsByArgumentsObj() {
  return arguments; // 객체
}

let argObj = getAllParamsByArgumentsObj('first', 'second', 'third')

console.log(argObj) 
// {'0': 'first', '1': 'second', '2': 'third',  length: 3}

console.log(Array.isArray(argumentsObj)) // false
// 배열은 아니지만 유사배열 (array-like) 객체이다. 

Array.from()

위에 이어서, 유사 배열을 배열로 만들어 준다.

const argsArr = Array.from(argumentsObj);
console.log(Array.isArray(argsArr))// true

더 공부해 볼 것

  • Deep Copy는 어떻게 할 수 있을까?
    수업시간에 거론된 재귀함수 외에도 여기에 보면 JSON.parse & JSON.stringify 방식도 있고 Lodash와 Ramda로도 가능하다고 한다.

::TODO::

출처

javascript 객체 복사하기
깊은 복사와 얕은 복사에 대한 심도있는 이야기

0개의 댓글