"원본을 바꾸지 않는다" 라고 하는 개념을 불변성
, 영어로 immutable
이라고 한다.
concat()
을 사용할 수도 있지만
concat()
의 경우 모든 연산에 대해서 불변인지 가변인지를 판단
해야 한다.
간단하게 Array.from()
API를 사용하면 새로운 배열이 만들어진다.
var a = [1,2];
var b = Array.from(a);
console.log(a,b,a==b);
---
> (2) [1, 2] | (2) [1, 2] | false
위 코드 실행 결과를 확인하면 a와 b의 출력은 동일하지만 a와 b는 같지 않는 것을 확인할 수 있다.
즉, a와 b는 내용이 같을 뿐 완전히 다른 배열이다.
var a = [1,2];
var b = Array.form(a);
b.push(3); // 이번엔 push 넣기
console.log(a,b,a==b);
---
> (2) [1, 2] | (3) [1, 2, 3] | false
위 코드처럼 b.push(3) 코드를 추가하여 b배열에 3을 넣게 될 때 b 배열에만 추가되는 것이다.
Array.from()
을 사용한 경우에는 push()
를 해도 원본 배열인 a 에 영향을 주지 않는다.
이전 챕터에 만든 애플리케이션에서 concat()
대신 Array.from()
을 적용할 수 있다.
App.js
>else if(mode === create)
구문_article = <CreateArti onSubmit = {function(_title, _desc){ this.max_content_id = this.max_content_id + 1; var newContents = Array.from(this.state.contents); // 임시 변수에 원본값 복사 newContents.push( // 임시변수.push활용 새로운 값 주입 {id:this.max_content_id, title:_title, desc:_desc} ); this.setState({ contents: newContents // 임시 변수를 입력 }); console.log(_title, _desc); }.bind(this)}><CreateArti>
- 실행결과
<Navi>
영역에 새로운 컨텐츠가 추가되고,
다른 목록을 클릭해도 해당<Navi>
영역의 컨텐츠는 그대로 유지한다.
변경하고자 하는 데이터인 this.state.contents
데이터를 Array.from()
을 통해 복사하고
이렇게 복제한 newContents
에 새로 추가하고 싶은 data
를 push()
하도록 변경한다.
변경한 코드를 실행시키면 정상적으로 동작하고, 다른 목록을 클릭할 경우 render()
함수가 호출되지 않는 것을 확인할 수 있다.
Array.from()
은 배열의 경우에만 쓸 수 있다.
객체인 경우에 객체 내용을 바꾸지 않고 새로운 복제된 객체를 만들고 싶다면
Object.assign()
을 사용한다.
var a = {name : 'kim'};
var b = Object.assign({},a);
console.log(a,b,a===b);
---
▶︎ {name: 'kim'} | {name: 'kim'} | false
Object.assign()
첫 번째 인자로는 빈 객체 혹은 새로운 객체를 주고, 두 번째로 a 객체를 준다.
콘솔 입력 결과 a 와 b 의 출력 내용은 동일하지만 서로 같은 것은 아닌 것을 확인할 수 있다.
- 즉,
Object.assign()
을 통해서 객체를 복제할 수 있고,- 배열은
Array.from()
을 통해서 할 수 있다.
추가로 첫번째 인자가 빈 객체가 아닌 경우의 출력도 확인해보자.
var a = {name:'kim'};
var b = Object.assign({left:1,right:2},a);
// b = {left: 1, right: 2, name: kim} 을 가진 상태다
b.name = 'lee';
console.log(a,b,a===b);
---
▶︎ {name: 'kim'} | {left: 1, right: 2, name: 'lee'} | false
첫번째 인자로 객체 {left:1,right:2}
가 들어가고 두번째 인자는 a 객체의 name
이 추가된 것을 확인할 수 있다.
이렇게 배열과 객체를 복제할 수 있는 다양한 방법이 있다.
현재 애플리케이션의 state를 변경한 방식을 살펴보자.
App.js
>render()
>return
render() { // 렌더 체크 console.log('App Render!'); // console.log('render', this); return ( <div className='App'> <Subject title={this.state.subject.title} sub={this.state.subject.sub} onChangePage={function () { // alert('myfcn!'); this.setState({ mode: 'welcome' }); // <== 해당 코드 }.bind(this)} ); }
this.setState({ mode: 'welcome' })
와 같은 코드는 원본을 교체하는 방식이다.this.state.contents.push()
를 수행한 것은 contents의 원본에 내용을 추가한 것이다.this.state.contents.concat()
을 사용한 방식은 원본을 교체한 것이다.Array.from()
을 사용한 것도 원본을 복제하여 그것으로 변경한 것이기 때문에 원본을 교체한 것이다.이처럼 까다로운 내용은 immutable
, immutable.js
를 검색해봐야 겠다.
자바스크립트의 배열을 사용할 때 push()
는 원본을 바꾸고 concat()
은 원본의 복제본으로 바꾸는 등 명령어들의 일관성이 떨어져서 해당 내용을 기억해야 하는 필요성이 있다.
이때 immutable.js
와 같은 라이브러리를 쓰면 유사 배열 유사 객체 같은 것을 만들고 이를 제어하는 방식은 반드시 immutable
한다.
무조건 불변이며, 무조건 원본을 바꾸지 않고 복제한 결과로 교체한 것을 리턴해준다.