JavaScript 데이터 - 객체(Object)
Object.prototype.메소드( ) 들은 리터럴 방식으로 사용 가능하나
Object.메소드( ) 같은 정적 메소드 들은 리터럴방식으로 사용 불가능하다. (선언 해야함)
따라서 Object.메소드( )의 형태로 사용해야 한다.
Object.assign( )
: 첫 번째 인수에 두 번째 인수를 병합하여 저장하는 함수.
Object.assign(target, ...sources)
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5};
const returnedTarget = Object.assign(target, source);
console.log(target);
// 결과: Object {a: 1, b: 4, c: 5}
console.log(returnedTarget)
// 결과: Object {a: 1, b: 4, c: 5}
console.log(target === returnedTarget)
// 결과: true
위의 예제를 보면 target 또한 병합 된 모습으로 저장된 것을 확인할 수 있다.
또한 target과 returnedTarget을 비교해보니 true가 출력되는 것을 확인할 수 있는데 이는 같은 메모리주소를 가리키고 있는 것을 의미한다.
const userAge = {
// key: value
name: 'Riam',
age: 72
}
const userEmail = {
name: 'Riam',
email: 'Riam@gmail.com'
}
const target = Object.assign(userAge, userEmail)
console.log(target)
// 결과 : {name: 'Riam', age: 72, email: 'Riam@gmail.com'}
console.log(userAge)
// 결과 : {name: 'Riam', age: 72, email: 'Riam@gmail.com'}
console.log(target === userAge)
// 결과 : True
const assa = { k: 123 }
const assb = { k: 123 }
console.log( assa === assb )
// 결과 : False
위의 코드를 살펴보면 target과 userAge를 비교해보면 true가 출력됨을 확인할 수 있다.
그러나 내용상으로 똑같은 assa와 assb를 비교해보면 false가 출력된다.
그 이유로는, 하나의 객체 데이터는 메모리에 저장되고, 객체 변수는 메모리의 주소만을 가지고 있어 변수가 호출될 때 메모리에 있는 내용을 '참조'하여 가져오기 때문이다.
이와 같은 데이터들을 '참조형 데이터'라고 부르며 배열, 객체, 함수 등이 여기에 해당된다.
위 코드에서는 assign 함수로 인해 userAge와 userEmail 객체가 userAge에 병합이 되었고, 그것을 target에 할당하였으므로 userAge와 target은 같은 메모리 주소를 가리키게 되어 target과 userAge가 같은 객체라고 인식이 되는 것이다.
비 참조형 데이터들은 선언 후 데이터 자체의 내용이 바뀌지 않으므로(불변) 같은 내용의 값을 할당하면 같은 메모리 주소를 가리키게 된다.
그러나 참조형 데이터들은 선언 후 데이터 자체의 내용이 변할 수 있으므로 같은 내용의 값을 할당하더라도 새로운 메모리 주소에 저장하게 되어 서로 다른 메모리 주소를 가리키게 된다.
const target = Object.assign({}, userAge, userEmail)
console.log(target) // {name: "Riam", age: 72, email: "Riam@gmail.com"}
console.log(userAge) // {name: "Riam", age: 72}
console.log(target === userAge) // false
이렇게 병합대상에 빈 객체 { } 를 넣게 되면 새로운 객체에 나머지 소스들을 병합하여 저장하게 되므로 원본을 변형시키지 않고 병합이 가능하다. 또한 userAge를 target에 할당한 게 아닌, 빈 객체를 할당한 것이므로 target과 userAge는 더이상 같은 객체를 가리키게 되지 않는다.
const target = Object.assign({}, userAge)
console.log(target === userAge) // false
이와같이 소스 객체를 하나만 지정하여 복사의 의미로도 사용이 가능하다. 이 때도 당연하게 target은 userAge와는 다른 객체이다.
Object.Keys()
: 객체의 '키' 들을 모아 배열 형태로 리턴시킨다.
const user = {
name: 'Riam',
age: 72,
email: 'Riam@gmail.com'
}
const keys = Object.keys(user)
console.log(keys) // 결과: ['name', 'age', 'email']
console.log(user['age']) // 결과: 72
const values = keys.map(key => user[key])
console.log(values) // 결과: ['Riam', 72, 'Riam@gmail.com']
key는 인덱싱 개념으로 객체 데이터에서 사용 가능하다.
구조 분해 할당 (비 구조화 할당, Destructuring Assignment)
만약 객체의 key를 객체 밖에서 사용하고 싶다면 구조를 분해하여 변수로 사용할 수 있다.
필요한 변수만 지정하여 사용이 가능하며 값이 없는 경우에는 디폴트 값을 설정해 줄 수 있다.
다만 변수를 설정하는 것이니만큼 같은 이름으로는 설정할 수 없다. 그 때는 : (콜론) 기호를 사용해서 이름을 바꿔줘야 한다.
const user = {
name: 'Riam',
age: 85,
email: 'Riam@gmail.com'
}
const {name, age, email, address = 'korea'} = user
// address는 없는 속성이므로 = 를 사용하여 디폴트 값을 지정해준다.
const user2 = {
name: 'Claudette',
age: 28,
email: 'Claudette@morrel.com'
}
const {name: name1} = user2
// name은 중복되는 값이므로 그대로 사용할 수 없고 name: name1 로 이름을 바꾸어 사용한다.
console.log(name) // Riam
console.log(address) // korea
console.log(name1) // Claudette
console.log('사용자의 나이는 ${age}세 입니다.')
// 사용자의 나이는 85세 입니다.
const fruits = ['Apple', 'Banana', 'Cherry']
const [, b, c] = fruits // [ ] 기호 사용하는 것에 주의
console.log(c) // Cherry
console.log(b) // Banana
구조분해는 비단 객체 뿐만이 아니라 배열에서도 사용 가능하다.
선언 시 대괄호를 사용하는 차이점이 있으며 쉼표로 구분하여 할당이 가능해, 필요하지 않은 부분은 비워두고 선언이 가능하다.
전개 연산자(Spread)
: 배열의 속성 '전체'나 일부를 제외한 '나머지'를 지정하는 연산자로, 반복 가능한(Iterable) 객체(배열)에서 사용이 가능하다.
const fruits = ['Apple', 'Banana', 'Cherry', 'Dragonfruit']
console.log(fruits) // 결과: ['Apple', 'Banana', 'Cherry']
console.log(...fruits) // 전개연산자. 결과: Apple Banana Cherry
//console.log(fruits[0], fruits[1], fruits[2], fruits[3])와 동일하다.
function toObject(a, b, c) {
return {
a: a,
b: b,
c: c
}
}
console.log(toObject(...fruits))
// 결과 {a: 'Apple', b: 'Banana', c: 'Cherry'}
function toSpreadObj(a, b, ...c) {
return {a, b, c}
}
console.log(toSpreadObj(...fruits))
// 결과: {a: 'Apple', b: 'Banana', c: ['Cherry', 'Dragonfruit']}
매개변수에도 사용이 가능하다. 매개변수의 개수만큼 앞에서 할당한다.
함수 정의 시에도 매개변수로 사용이 가능한데, 이 때는 앞부분에서부터 정해진 변수를 할당하고 나머지 부분을 전개 연산자부분에 배열로 할당이 된다.