one of the JavaScript's data types.
a collection of related data and/or functionality.
Nearly all objects in JavaScript are instances of Object.
오브젝트는 프로퍼티의 집합
이며 프로퍼티는 key
와 value
로 구성된다.
Objects can be created using the Object() constructor
or the object initializer / literal syntax
.
const obj1 =
new
Object()
;
const obj2 ={}
; ✔️
⭐ 객체 내에는 문자열, 숫자, 함수, 배열, 객체, 불리언, 기호 등 다양한 데이터 유형을 포함할 수 있다.
➕ 객체 프로퍼티로 할당된 함수를 메소드라고 한다.
: 위처럼 오브젝트 생성한 후에 프로퍼티를 추가/삭제할 수도 있다.
삭제 :
delete
연산자 사용
JavaScript 오브젝트에서 computed properties(계산된 프로퍼티)은 오브젝트의 속성 이름을 동적으로 계산하여 만들 수 있는 기능을 말하는 것으로, 속성명을 대괄호 []
로 둘러싸서 표현한다.
[ppp]는 프로퍼티명을 동적으로 계산하며,
ppp 변수의 값에 따라 프로퍼티명이 결정된다.
이런 식으로 대괄호로 묶어 표현하면
ppp라는 문자열이 아니라 변수 ppp에 할당된 값이 들어가기 때문이다.
❔ 그럼 혹시 저 변수에 담긴 값이 이후에 바뀌면 오브젝트의 프로퍼티명도 자동으로 바뀔까? 🔽
※ 객체가 생성될 때 프로퍼티 이름은 그 순간에 정해진 것이며, 이후에 변수 ppp의
값이 변경되더라도 이미 생성된 객체의 프로퍼티 이름은 변경되지 않는다.
객체의 구조를 변경하려면 프로퍼티를 직접 수정해야 한다.
(kid-name 프로퍼티 추가, name 프로퍼티 삭제)
❔ 어떨 때 유용할까 ?
⭐️ key는 항상 string 데이터타입으로 전달해야 한다!
위 함수는 속성 키를 동적으로 참조하려 하나, 에러가 발생했다.
.
을 사용하면 실제로 객체 name 의 속성 중에 'key'라는 속성을 찾아 참조하려는 것으로 해석되기 때문이다. 즉, 'key'가 문자열이 아닌 실제 속성의 이름으로 해석되어 'key'라는 key가 있는지 찾는다.
그러나 'hoony'객체에 ‘key’라는 속성은 없기 때문에 (존재하지 않는 프로퍼티에 접근하려 하면 undefined를 반환한다) ReferenceError가 발생하는 것이다.
수정 ⤵️
사용자에게 어떤 key를 입력받아 출력하는 함수를 만드는 경우, 당시에는 사용자가 어떤 key를 입력할지 알 수가 없다. 따라서 이러한 경우에는 계산된 프로퍼티를 사용하여 속성 이름을 동적으로 생성하는 것이 유용하다 !
참고
Object Literal Property Value 축약어
: 속성 값이 속성 식별자와 이름이 같다면 생략이 가능하다.
function createMonster(name, power) { return { type: 'Monster' , name: name , power: power }; } ⬇️ function createMonster(name, power) { return { type: 'Monster', name, power }; }
참고
➕
이전에 JS에 클래스가 없었을 때는,
다른 계산을 하지 않고 오브젝트만 만드는 함수를 만들어 쓰기도 했다 ( = 클래스에서 constructor의 역할).function makePerson(name, age){ return { name = name; age = age; } } 호출 : makePerson('mina', 8); ⬇️ function Person(name, age){ // 주로 대문자로 시작 this.name = name; this.age = age; } 호출 : const mina = new Person('mina', 8);
in
오브젝트 안에 특정 프로퍼티가 존재하는지 여부를 확인할 수 있다.
첫 번째 예시 같은 경우 `.`이나 `[]`을 이용하는 것이 더 간단해 보인다. 그러나 두 번째 예시 같은 경우에는 `in`을 사용하는 것이 유용하다.
for
( keyin
object )
: 오브젝트의 모든 key들을 받아 올 수 있다.
tameCat이 가지고 있는 key 값들이 모두 출력된 모습
🟰
tameCat['name']
tameCat['owner']
tameCat['age']
for
( valueof
iterable ) : 배열과 같은 iterable 객체에 사용이터러블 객체는 반복문을 사용하여 내부 요소를 순회할 수 있는 객체를 나타낸다.
Reference 데이터 타입 변수의 경우 Primitive 데이터 타입인 경우와 달리 실제로 데이터를 보유하지 않고 해당 데이터의 레퍼런스를 가리키고 있다. 그리하여 이러한 변수를 다른 변수에 할당하게 되었을 때에도 레퍼런스를 할당해 주게 된다.
그럼 두 변수는 동일한 레퍼런스를 가지게 되기 때문에 (실제로는 하나의 객체나 배열을 공유하고 있기 때문에) 만약 이 중 하나의 변수를 통해 객체나 배열 등을 변경하게 되면 그것을 참조하고 있던 나머지 변수의 값들도 바뀌게 된다.
fruit과 fruit2는 동일한 객체를 가리키게 되므로
fruit의 프로퍼티를 변경하면 fruit2에도 동일한 변경사항이 반영된다.
반대로 fruit2의 프로퍼티를 변경해도 fruit에 반영된다.
그럼 어떻게 해야 할까?
shallow copy : duplicate as little as possible.
for in을 사용하여 순회하며 수동적으로 일일이 프로퍼티를 할당
Object.assign (
target
,source1, source2, ··· , sourceN
)
target
: 원본 속성을 적용할 대상
source
: 복사하고자 하는 오브젝트. 여러 개 전달 가능
// 소스
const fruit = { name : 'strawberry', color : 'red' };
const drink = { name : 'coffee', temperature : 'hot'};
예시 🔽
target이 빈 깡통
일 경우 // 1.
const target = {};
Object.assign(target, fruit);
// 2.
const target = Object({}, fruit);
// 1과 2는 동일한 코드이다.
console.log(target) 🔽
동일한 프로퍼티를 가진 source 여러 개를 적용
한 경우 // 두 오브젝트 모두 name 속성을 가지고 있다.
const target = Object({}, fruit, drink);
console.log(target) 🔽
fruit과 drink가 공통적으로 가진 프로퍼티였던 name은
뒤에 작성된 drink의 것이 적용되었다.
뒤에 작성된 소스가 (앞에 동일한 프로퍼티가 있다면) 값을 계속 덮어 씌우기 때문이다.
source가 배열
인 경우deep copy : duplicate everything.
참조
https://dev.to/edwardluu/understanding-deep-and-shallow-copy-in-javascript-4im0