비구조화 할당으로도 잘 알려진 문법입니다.
즉 잘 구조화된 객체의 값을, 비구조화시켜서 변수에 개별적으로 각각 할당한다는 의미에요.
🙆🏻 사실 이게 끝이에요. 정말로요.
🚦 사실 이 내용은 책에 들어있지 않아요.
그렇기에 근거는 서술되어 있으나, 주관이 많이 들어가 있는, 확실하지 않은 내용입니다!
혹시나 제 의견에 오류가 있다면 댓글로 남겨주세요. 비판은 환영입니다 🥰
좀 더 내부를 이해해야지, 사실 이 디스트럭처링 할당의 기능을 비로소 이해 가능해요.
우리 이터러블 챕터에서 iterator
라는 것을 배웠어요.
이터레이션 프로토콜을 제대로 준수한 이터러블의 이터레이터 객체는 next
메서드를 통해 순회를 합니다. 그리고 그 순회로
그렇게 하나하나~ 할당되면, 어느 순간 더이상 할당할 수 없겠죠?
그러면 실행이 끝나는 형식이에요. 더이상 할당하라는 명령이 없기 때문입니다.
이제 한 번 재밌는 놀이를 해보죠!
스프레드와 디스트럭처링은, 과연 이터러블인 배열에서 어떻게 동작할까요?
const arr = [1,2,3,4];
arr[Symbol.iterator] = function () {
let idx = 0;
return {
next() {
console.log('test')
return { value: arr[idx], done: idx++ === arr.length };
}
};
}
// 새롭게 할당되는 과정에서 `[Symbol.iterator]()`를 호출해내고,
// 이터레이터 객체에 내장된 `next` 메서드를 강제 수행한다.
const [a, b] = arr;
// 출력이 된다는 것은, iterator 객체의 next 메서드를 수행했다는 의미이다.
// test
// test
console.log(a, b) // 1 2
// spread는 iterable.next()를 수행한다. 따라서 test가 출력된다.
c = [...arr];
// test
// test
// test
// test
// test
console.log(c)
// [1,2,3,4]
요~게 가장 재미있습니다. 커스텀한 이터러블 객체는 어떻게 동작할까요?
우리 복습차원에서, 아까 했던 내용을 정리해봐요!
iterator
객체에 리턴된 next
메서드를 활용한다.결과를 말씀드리자면, 객체의 디스트럭처링에서는 활용되지 않습니다.
왜냐! 일단 객체가 non-iterable
입니다. 그럼에도 불구하고, 객체는 디스트럭처링이 동작합니다!
const obj = {a: 1, b: 2};
const {a, b} = obj
console.log(a, b) // 1, 2
// 추가로, 스프레드 문법도 객체 리터럴 내부에서는 non-iterable이어도 동작합니다.
console.log({ ...obj })
따라서 우리는 이 예제를 통해, 이렇게 가설을 정의할 수 있겠군요.
iterator
객체의 next
메서드를 호출한다.Object
는 이미 다른 연산을 통해 문법이 구성되어 있어, 이터레이터 객체의 next
메서드를 호출하지 않을 것이다.const iterableObject = {
a: 1,
b: 2,
2: 3,
3: 4,
4: 5,
[Symbol.iterator]() {
let cur = 0;
const max = Object.keys(iterableObject).length;
return {
next() {
console.log('test')
return { value: iterableObject[cur], done: cur++ === max };
}
};
}
};
// 객체에서의 디스트럭쳐링은 직접 인덱스로 접근하여 재할당하는 방식입니다.
// 따라서 `iterator`을 호출하지 않아요.
const {a, b} = iterableObject
console.log(a,b) // 1 2
const iterableObject = {
0: 1,
1: 2,
2: 3,
3: 4,
4: 5,
[Symbol.iterator]() {
let cur = 0;
const max = Object.keys(iterableObject).length;
return {
next() {
console.log('test')
return { value: iterableObject[cur], done: cur++ === max };
}
};
}
};
// 객체에서의 스프레드 문법 역시 따로 구현되어 있는 상태입니다.
// 따라서 `iterator` 객체의 `next` 메서드를 호출하지 않아요.
{...iterableObject} // {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, Symbol(Symbol.iterator): ƒ}
next
를 호출해내는 방법그렇다면, 이를 호출하게 하려면 어떻게 해야 할까요?
우리는 이터레이션 프로토콜을 준수한 이터러블의 특성을 이용하면 됩니다.
이터레이션의 프로토콜을 준수하면 스프레드 문법을 통해 일련의 값들을 담아올 수 있죠?
따라서, 다음과 같이 하면 next
메서드를 호출시킬 수 있답니다 🥰
next
를 호출하여 값을 생성해낸다.// 위의 예제인 iterableObject를 사용했어요.
console.log([...iterableObject]);
// test
// test
// test
// test
// test
// [1, 2, 3, 4, 5]
결국 이를 통해, 빌트인 이터러블과, 객체는 실제로 디스트럭처링 과정에서 동작이 완전히 다르다는 것을 알게 되었네요!
정말 사실 빠르게 넘기려 했는데, 이 과정이 너무 신기하다 보니 가설을 증명하는 데까지 거의 2시간을 썼네요.
역시 뭔가를 파고드는 건 정말 재밌는 것 같아요. 다들 즐거운 공부하시길 바라며, 이상!