# 객체 문법
# 객체
- 몇 가지 특수한 기능을 가진 연관 배열associative array
- 자료구조의 하나로, 키 하나와 값 하나가 연관되어 있으며 키를 통해 연관되는 값을 얻을 수 있다.
- 객체 기반 패러타임이 자바스크립트
- 객체는 프로퍼티의 집합
# 일반 객체 이외 여러 종류의 객체
# 내장 객체 (Built in Object)
원시값을 제외한 다른 내장 객체는 Object 의 하위 집합이다.
Array
– 정렬된 데이터 컬렉션Date
– 날짜와 시간 정보Error
– 에러 정보- etc
# typeof null === 'object' ?
null 은 primitive 이지만 typeof null
은 object
인 이유가 무엇일까?
자바스크립트를 처음 구현할 때
- 자바스크립트 값 :
타입 태그
+값
type tag
(1~3 비트) +실제 값
32비트 단위로 저장- 타입 태그 (object: 000, int: 1, double: 010, string: 100, boolean: 110)
- 객체의 타입 태그는 0.
- null 은 Null pointer(대부분의 플랫폼에서 0x00)로 표시됨.
- null 은 보편적으로 아무것도 없음을 의미하기 때문에
- 그 결과 null 은 타입 태그로 0을 가지며, 따라서 typeof 는 object 를 반환합니다.
ECMAScript에 수정 제안(opt-in을 통해)
- typeof null === 'null'.
- null type check 를 위한 코드 typeof null === "object" 의 하위 호환을 맞추기 위함.
- 제안은 거절 됨.
# 객체의 생성(초기화)
new Object()
{ }
Object.create()
# 리터럴 이외의 객체 생성 지양 이유
그래도 3가지 방법으로 만들 수 있게 한 자바스크립트의 철학이 있지 않을까? TODO
- property 추가가 어렵다.
Object 를 생성하고, 하나씩 프로퍼티를 추가해야 한다.
const Square = new Object();
Square.width = 300;
Square.height = 300;
1
2
3
2
3
const Rectangle = new Object();
Object.assign(Rectangle, { width: 300, height: 300 });
1
2
2
- Object 리터럴은 코드 길이가 작다.
# 프로퍼티
- 프로퍼티(키-값 쌍)를 저장
- 프로퍼티는 이름 값의 관계
- 프로퍼티 키 : 문자열, 심볼
- 프로퍼티 값 : 모든 자료형
# 프로퍼티 이름
- 프로퍼티 값에 접근하기 위한 레퍼런스 역할
- 객체 컨테이너에 보관됨
# 프로퍼티에 접근 및 추가
# 점 표기법: obj.property
- 자바스크립트 변수 이름 생성 규칙 (_$0-9, A-Z,a-z) 에 허용 되는 문자열.
# 대괄호 표기법 obj["property"]
UTF-8 / Unicode 호환 문자열
obj[varWithKey]
같이 변수에서 키를 가져올 수 있다.const a = {}; a['Awesome-Property!'] = 1;
원시값을 사용하면 문자열로 변환된 뒤에 사용된다.
const obj = {}; obj[null] = 'NULL'; obj[true] = 'TRUE'; obj[obj] = 'Object'; console.log(obj['null']); // 'NULL' console.log(obj['true']); // 'TRUE' console.log(obj['[object Object]']); // 'Object'
1
2
3
4
5
6
7
8[ES6]계산된 프로퍼티 이름
- 객체 리터럴 내부에서 프로퍼티 이름을 [] 로 감싼 뒤 계산된 프로퍼티 이름을 사용할 수 있다.
const meow = 'MEOW'; const obj = { [meow]: 'NYAN', [meow+meow]: 'NYAN NYAN', }; console.log(obj['MEOW']) // 'NYAN' console.log(obj['MEOWMEOW']) // 'NYANNYAN'
1
2
3
4
5
6
7
8 - ES6 심볼 사용
const objWithSymbol = { [Symbol.Private]: "Private" }; console.log(objWithSymbol[Symbol.Private]) // "Private"
1
2
3
4
5
- 객체 리터럴 내부에서 프로퍼티 이름을 [] 로 감싼 뒤 계산된 프로퍼티 이름을 사용할 수 있다.
# 프로퍼티를 삭제
delete obj.prop
# 객체가 특정 프로퍼티를 가지고 있는지 확인
"key" in obj
프로퍼티 값을 undefined 로 할당할 경우 실패할 수 있다.
let obj = {
test: undefined
};
alert( obj.test ); // 값이 `undefined`이므로, 얼럿 창엔 undefined 가 출력됩니다. 그런데 프로퍼티 test 는 존재합니다.
alert( "test" in obj ); // `in`을 사용하면 프로퍼티 유무를 제대로 확인할 수 있습니다(true 가 출력됨).
1
2
3
4
5
6
7
2
3
4
5
6
7
- undefined
- 변수는 정의되어 있으나 값이 할당되지 않은 경우
- 프로퍼티 값이 undefined 인 경우는 흔치 않다 ?
- 값을 알 수 없거나(unknown) / 비어 있다는(empty) -> 주로 null
# 객체의 모든 키를 순회
for (let key in obj)
let user = {
name: "John",
age: 30,
isAdmin: true
};
for (let key in user) {
// 키
alert( key ); // name, age, isAdmin
// 키에 해당하는 값
alert( user[key] ); // John, 30, true
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 객체 정렬 방식
- 정수 프로퍼티 -> 오름 차순 정렬
- 정수 외 프로퍼티 -> 객체에 추가한 순서대로 정렬
# 정수 프로퍼티
변형 없이 정수에서 문자열 사이에 변환
// 함수 Math.trunc는 소수점 아래를 버리고 숫자의 정수부만 반환합니다.
alert( String(Math.trunc(Number("49"))) ); // '49'가 출력됩니다. 기존에 입력한 값과 같으므로 정수 프로퍼티입니다.
alert( String(Math.trunc(Number("+49"))) ); // '49'가 출력됩니다. 기존에 입력한 값(+49)과 다르므로 정수 프로퍼티가 아닙니다.
alert( String(Math.trunc(Number("1.2"))) ); // '1'이 출력됩니다. 기존에 입력한 값(1.2)과 다르므로 정수 프로퍼티가 아닙니다.
1
2
3
4
2
3
4
- 정수 프로퍼티(integer property)는 자동으로 정렬
let codes = {
"49": "독일",
"41": "스위스",
"44": "영국",
// ..,
"1": "미국"
};
for (let code in codes) {
alert(code); // 1, 41, 44, 49
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
정렬되지 않은 정수 프로퍼티 만들기
let codes = {
"+49": "독일",
"+41": "스위스",
"+44": "영국",
// ..,
"+1": "미국"
};
for (let code in codes) {
alert( +code ); // 49, 41, 44, 1
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 객체의 복사
얕은 복사
Object.assign
- Object Spread Operator ({...});
- object(배열, 함수 포함) 이면, 참조로 복사 되기 때문에 배열, 객체, 함수에 대한 변경이 생기면 모든 복사된 객체가 공유한다
깊은 복사
JSON.stringify
&JSON.parse
- JSON 직렬화가 불가능한 함수는 프로퍼티가 될 수 없다.
- Structured cloning algorithm
- lodash 의 메서드인 _.cloneDeep(obj)
# ES6 Object Syntax
const doondoony = {
name: 'DoonDoony',
age: 3,
favorite: 'Red Ball',
color: ['white', 'coffee'],
};
1
2
3
4
5
6
2
3
4
5
6
- Object Spread Operator doondoony 객체의 모든 값을 복사하고, 중복되는 프로퍼티는 업데이트
const doondoonyJr = { ...doondoony, name: 'DoonDoon', age: 1 };
1
- Rest Parameter
const { name, ...rest } = doondoony;
const { catName, ...rest } = doondoony;
1
2
2
- Object Destructuring
const { name, age } = doondoony;
function howOldAreYou ({ name, age }) { }
1
2
3
2
3
- Property Value Shorhand (프로퍼티 할당 단축구문)
function makeCuteCat (name, age, color) {
return {
name, // name: name 이라고 원래는 작성해야 했었지만, 단축 구문을 사용하면 같은 동작을 합니다
age,
color,
};
}
1
2
3
4
5
6
7
2
3
4
5
6
7
- Method definition shorthand(메서드 정의 축약 문법)
const doondoony = {
// speak: function() {} 과 같은 방식에서 축약 해서 작성할 수 있습니다
speak () {
console.log(this.name);
},
};
1
2
3
4
5
6
2
3
4
5
6