dart에는 spread 연산자가 있어서 타언어보다 쉽게 깊은 복사가 가능하다.
void main() {
var list = [1,2,3];
var newList = [...list];
print(list);
print(newList);
list[0] = 10;
print(list);
print(newList);
}
결과에서 보이는 것처럼 스프레드 연산자를 이용하여 복사를 하면 레퍼런스 복사(메모리 주소를 복사)가 아닌 데이터 값자체를 복사해오는 깊은 복사를 한다. 타언어에서 깊은 복사를 할때와 비교해보면 굉장히 수월하게 깊은 복사를 수행할 수 있다.
하지만 주의해야할 것이 있는데...
void main() {
var list = [{"id":1}, {"id":2}];
var subList = list;
var newList = [...list];
print(list);
print(newList);
list[0]["id"] = 10;
print(list);
print(newList);
print(list.hashCode);
print(newList.hashCode);
print(subList.hashCode);
}
위와 같이 맵을 스프레드 연산자로 복사하게 되면 분명 메모리 주소는 다른 깊은 복사를 하는데 list의 값을 변경시켰을 때 newList의 값도 변경되는 현상이 일어난다. 이것은 list 객체 자체는 깊은 복사를 하지만 내부에 있는 map을 얕은복사를 하기 때문에 나타나는 현상이다.
이를 해결하기 위해서는
var newList = list.map((i)=>{...i}).toList();
와 같이 리스트에 있는 맵을 람다식으로 하나하나 찾아서 스프레드 연산을 해야한다.
스프레드 연산을 활용하면 단순히 복사뿐만 아니라 삽입, 삭제와 수정도 할 수 있다.
void main() {
// 수정
var users = [
{"id":1, "username":"thekim12", "password":1234},
{"id":2, "username":"metacoding", "password":5678},
];
var newUsers = users.map((i)=>i["id"]==2 ? {...i, "username":"love"}: i).toList();
print(newUsers);
// 삽입
var test = [1,2,3,4];
var newTest = [...test, 5];
print(newTest);
}