《 Data Type의 메모리 할당 》에 대해 안다는 전제 하에 포스팅합니다.
// user 객체를 생성
var user = {
name: 'wonjang',
gender: 'male',
};
// 이름을 변경하는 함수, 'changeName'을 정의
// 입력값 : 변경대상 user 객체, 변경하고자 하는 이름
// 출력값 : 새로운 user 객체
// 특징 : 객체의 프로퍼티(속성)에 접근해서 이름을 변경 -> 가변
var changeName = function (user, newName) {
var newUser = user;
newUser.name = newName;
return newUser;
};
// 변경한 user정보를 user2 변수에 할당
// 가변이기 때문에 user1도 영향을 받게 된다.
var user2 = changeName(user, 'twojang');
// 아래 로직 skip
if (user !== user2) {
console.log('유저 정보가 변경되었습니다.');
}
// user과 user2이 똑같아지는 현상 발생 -> 똑같은 주소 가리킴
console.log(user.name, user2.name); // twojang twojang
console.log(user === user2); // true
위의 예제를 아래와 같이 개선할 수 있다. (새로운 객체 리턴(새 주소 할당)하는 방식 → 불변)
// user 객체를 생성
var user = {
name: 'wonjang',
gender: 'male',
};
// 이름을 변경하는 함수 정의
// 입력값 : 변경대상 user 객체, 변경하고자 하는 이름
// 출력값 : 새로운 user 객체
// 특징 : 객체의 프로퍼티에 접근하는 것이 아니라, 아예 새로운 객체를 리턴(새 주소를 할당하게 됨) -> 불변
var changeName = function (user, newName) {
return {
name: newName,
gender: user.gender,
};
};
// 변경한 user정보를 user2 변수에 할당
// 불변이기 때문에 user1은 영향이 없다.
var user2 = changeName(user, 'twojang');
// 아래 로직이 정상적으로 수행
if (user !== user2) {
console.log('유저 정보가 변경되었습니다.');
}
console.log(user.name, user2.name); // wonjang twojang
console.log(user === user2); // false
불변성을 유지하는 방법 중 하나이다.
바로 아래 단계의 값만 복사한다.
var copyObject = function (target) {
var result = {};
// for ~ in 구문을 활용하여, 객체의 모든 프로퍼티에 접근 -> 하드코딩 필요 x
// 이 copyObject로 복사를 한 다음, 복사를 완료한 객체의 프로퍼티를 변경
for (var prop in target) {
result[prop] = target[prop];
}
return result;
}
// user은 항상 copyObject를 사용해 복사 (새 주소 할당 -> 불변성 유지)
var user = {
name: 'wonjang',
gender: 'male',
};
var user2 = copyObject(user);
user2.name = 'twojang';
if (user !== user2) {
console.log('유저 정보가 변경되었습니다.');
}
console.log(user.name, user2.name);
console.log(user === user2);
var user = {
name: 'wonjang',
urls: {
portfolio: 'http://github.com/abc',
blog: 'http://blog.com',
facebook: 'http://facebook.com/abc',
}
};
var user2 = copyObject(user);
user2.name = 'twojang';
// 바로 아래 단계에 대해서는 불변성을 유지하기 때문에 값이 달라진다.
console.log(user.name === user2.name); // false
// 더 깊은 단계에 대해서는 불변성을 유지하지 못하기 때문에 값이 같다.
user.urls.portfolio = 'http://portfolio.com';
console.log(user.urls.portfolio === user2.urls.portfolio); // true
// 아래 예도 똑같다.
user2.urls.blog = '';
console.log(user.urls.blog === user2.urls.blog); // true
내부의 모든 값들을 하나하나 다 찾아서 모두 복사한다. (얕은 복사의 한계 해결)
var user = {
name: 'wonjang',
urls: {
portfolio: 'http://github.com/abc',
blog: 'http://blog.com',
facebook: 'http://facebook.com/abc',
}
};
// 1차 copy
var user2 = copyObject(user);
// 2차 copy -> 이렇게까지 해줘야만 해요..!!
user2.urls = copyObject(user.urls);
user.urls.portfolio = 'http://portfolio.com';
console.log(user.urls.portfolio === user2.urls.portfolio);
user2.urls.blog = '';
console.log(user.urls.blog === user2.urls.blog);
따라서 재귀적 수행을 사용하여 깊은 복사를 완벽 구현할 수 있다.
var copyObjectDeep = function(target) {
var result = {};
if (typeof target === 'object' && target !== null) {
for (var prop in target) {
result[prop] = copyObjectDeep(target[prop]); // 재귀적 수행
}
} else {
result = target;
}
return result;
}
//결과 확인
var obj = {
a: 1,
b: {
c: null,
d: [1, 2],
}
};
var obj2 = copyObjectDeep(obj);
obj2.a = 3;
obj2.b.c = 4;
obj2.b.d[1] = 3;
console.log(obj);
console.log(obj2);
가장 아래의 코드가 실행 되었을 때, “Passed ~” 가 출력되도록 getAge 함수를 채워보자.
var user = {
name: "john",
age: 20,
};
var getAged = function (user, passedTime) {
// 여기를 작성해 주세요!
};
var agedUser = getAged(user, 6);
var agedUserMustBeDifferentFromUser = function (user1, user2) {
if (!user2) {
console.log("Failed! user2 doesn't exist!");
} else if (user1 !== user2) {
console.log(
"Passed! If you become older, you will be different from you in the past!"
);
} else {
console.log("Failed! User same with past one");
}
};
agedUserMustBeDifferentFromUser(user, agedUser);
var getAged = function (user, passedTime) {
var newUser = user;
newUser.age += passedTime;
return newUser; // Failed! User same with past one
};
console.log(user1); // { name: 'john', age: 26 }
console.log(user2); // { name: 'john', age: 26 }
// 객체 만들어 프로퍼티 복사하기
var getAged = function (user, passedTime) {
var result = {};
for (var prop in user) {
result[prop] = user[prop];
}
result.age += passedTime;
return result;
};
var user = {
name: "john",
age: 20,
}
// 객체 만들어 프로퍼티 복사하기
var getAged = function (user, passedTime) {
var result = {};
for (var prop in user) {
result[prop] = user[prop];
}
result.age += passedTime;
return result;
}
var agedUser = getAged(user, 6);
var agedUserMustBeDifferentFromUser = function (user1, user2) {
if (user1 !== user2) {
console.log("Passed! If you become older, you will be different from you in the past!")
} else {
console.log("Failed! User same with past one");
}
}
agedUserMustBeDifferentFromUser(user, agedUser);