728x90
사건의 발단
같은 팀원분의 코드리뷰를 하다가 아래와 같은 코드를 만났다.
... 생략
this.setState = nextState => {
const {isLoading, nodes, selectedImageUrl, paths} = this.state
this.state = nextState
if (nodes !== this.state.nodes) {
nodeItems.setState({
isRoot: this.state.isRoot,
nodes: this.state.nodes
})
}
... 생략
}
나는 일말의 고민도 하지 않고 자바스크립트의 객체(배열)를 일치 연산자로 비교할 경우 메모리의 주소값으로 비교하기 때문에 당현히 false로 평가가 된다고 생각하였고 (코드에서 비교하고 있는 nodes는 배열이다.) 그렇게 리뷰를 남겨드렸다.
하지만 결과적으로 내가 남겨드린 리뷰는 틀린 리뷰였다!!
그 이유는 저 부분만 보고 해석을 했기 때문이다. (숲을 보지않고 나무만 본 격...)
그럼 상세한 내용은 아래에서 알아보자.
다시 톺아보기
이해하기 쉽게 더 간단한 코드로 확인해 봤다.
const newNodes = ['a', 'b', 'c'];
function App() {
this.state = {
isLoading: false,
nodes: newNodes,
};
this.setState = nextState => {
const { nodes } = this.state;
this.state = nextState;
console.log(nodes === this.state.nodes);
};
this.test = () => {
this.setState({ ...this.state, nodes: newNodes }); // true로 평가됨
this.setState({ ...this.state, nodes: ['a', 'b', 'c'] }); // false로 평가됨
};
}
const app = new App();
app.test();
내가 숲을 보지않고 나무를 봤다고 했는데, 여기서 내가 보지못한 그 숲은
this.setState({ ...this.state, nodes: newNodes }); 부분이라 할 수 있다. 기본적으로 자바스크립트의 전개연산자는 얕은 복사를 하기 때문에 객체 내부의 프로퍼티는 재할당 되지 않는 이상 같은 주소값을 가지고 있다.
그래서 nextState의 nodes와, this.state의 nodes는 같은 newNodes를 가리키고 있기 때문에 true로 평가가 되는것이다.
내가 생각했던 코드는 this.setState({ ...this.state, nodes: ['a', 'b', 'c'] }); 와 같은 경우일 때 이다. nodes에 새로운 배열이 할당되었기 때문에 주소값이 달라지게 되므로 false로 평가 된다!
아래 코드를 보면 더 이해하기 쉬울 것이다.
const origin = { name: 'aB', age: '99' };
const copy = { ...origin };
console.log(origin === copy); // false
console.log(origin.name === copy.name); // true
copy.name = 'cD';
console.log(origin.name === copy.name); // false
한 줄 결론
숲을 보자...😭
728x90
댓글