Objects
- 객체형에는 다양한 데이터를 담을 수 있는 연관 배열(associative array)
- 키(key)로 구분된 데이터 집합이나 복잡한 개체(entity) 저장 가능
- {프로퍼티(property) - 키(key): 값(value)}
- {..} : 객체 리터럴(object literal)
Literals and properties
let user = {
name: "John",
age: 30,
"is admin":true,
};
alert( user.name );
alert( user.age );
- 콜론(:)을 기준으로 왼쪽 키, 오른쪽 값
- 프로퍼티 키는 프로퍼티 이름 또는 식별자라고도 불림
- 점 표기법(dot notation)으로 프로퍼티 값 읽기
- 프로퍼티 값 추가/삭제(delete) 가능
- 여러 단어로 프로퍼티 이름을 생성할 시 따옴표("") 표기
- trailing, hanging 쉼표 : 마지막 프로퍼티 끝에 쉼표 가능
Square brackets
user.is admin = true
user["is admin"];
user[key] = value;
- 대괄호 표기법(square brackets)
- 여러 단어로 생성한 프로퍼티 이름은 점 표기법 사용 불가하여 대괄호 표기법 사용
- 프로퍼티 변수 값에 접근 가능
let fruit = prompt("어떤 과일을 구매하시겠습니까?","apple");
let bag = {
[fruit] : 5
[fruit + 'Computers'] : 1
};
alert ( bag.apple );
alert ( bag.appleComputers );
- 계산된 프로퍼티(computed property)
- 대괄호 [] 와 같이 사용하여 복잡한 표현식 가능
Property value shorthand
function addUser(name, age) {
return {
name,
age
};
}
- 프로퍼티 값에 변수를 사용해 만드는 경우 프로퍼티 값 단축 구문으로 가능
Property names limitations
- 객체 프로퍼티 이름에는 특별한 제약이 없음
- 예약어(for, let, return, etc.)도 문자열로 자동 형 변환 되어 사용 가능
- _proto_만 제한
Property existence test, "in" operator
let user = {};
alert( user.noSuchProperty === undefined );
alert( "key" in object );
- 존재하지 않는 프로퍼티에 접근하는 경우 undefined 반환
- 존재 여부를 확인하는 방법
- === undefined 비교 : true 존재하지 않음
- "key" in object : true 존재 / false 존재하지 않음
The "for..in" loop
for (let key in object) {
alert( key );
alert( object[key] );
}
- 반복 변수(looping variable) 선언하여 사용, 다른 변수명 가능
Ordered like an object
- 키가 정수 프로퍼티(integer property)인 경우 자동 정렬
- 그 외의 프로퍼티는 객체에 추가한 순서로 정렬
Object references and copying
- 객체는 '참조에 의해(by reference)' 저장 및 복사
- 객체가 저장되어 있는 '메모리 주소 = 참조 값'이 저장됨
- 원시값(프리미티브 타입)은 값 그대로
- 동일한 객체에 대해 접근하거나 조작하기 위해 여러 변수를 사용할 수 있음
- 객체가 하나의 서랍장이라면 변수는 서랍장을 열 수 있는 열쇠
Comparison by reference
- 두 객체가 같은 객체를 참조하는 경우 true 반환
Cloning and merging, Object.assign
- 기존 객체와 같으면서 독립적인 새로운 객체를 복제하려는 경우
- 새로운 객체 생성 후 기존 객체의 프로퍼티들을 순회하여 복사
- Object.assign 사용
Object.assign(dest, [src1, src2, ...])
- dest : 대상 객체
- srcN : 복사하려는 객체
- 객체 srcN들의 모든 프로퍼티를 dest에 복사하고, dest 반환
Nested cloning
- 깊은 복사(deep cloning)
- 프로퍼티 값이 다른 객체에 대한 참조 값인 경우
- 각 obj[key]의 값을 검사하면서, 그 값이 객체인 경우 구조도 함께 복사하는 반복문 사용
Garbage collection
Reachability
- 자바스크립트 엔진에서는 모든 객체를 모니터링하고 도달할 수 없는 객체는 삭제하는 가비지 컬렉터(garbage collector)가 동작함
- 자바스크립트는 도달 가능성(reachability)을 통해 메모리 관리 수행
- '도달 가능한 값'은 어떻게든 접근하거나 사용할 수 있는 값을 의미
- 현재 함수의 지역 변수와 파라미터
- 중첩 함수의 체인에 있는 함수에서 사용되는 변수와 파라미터
- 전역 변수 등
- 루트가 참조하는 값이나 참조할 수 있는 값
A simple example
let user = {
name: "John"
};
user = null;
Two references
let user = {
name: "John"
};
let clone = user;
user = null;
Interlinked objects
function marry(man, woman) {
woman.husband = man;
man.wife = woman;
return {
father: man,
mother: woman
}
}
let family = marry({
name: "John"
},{
name: "Ann"
});

- 전역 객체 family는 father(John) / mother(Ann)로 연결됨
- father(John)과 mother(Ann)는 wife, husband로 연결됨
delete family.father;
delete family.mother.husband;
- 만약 두 개의 참조를 삭제하면 John으로 들어오는 참조가 모두 삭제되어 Object(John)는 메모리에서 삭제됨
- John에서 외부로 나가는 참조는 영향을 주지 않음
Unreachable island
- 객체들이 연결되어 섬과 같은 구조를 만드는데, 이 섬에 도달할 방법이 없는 경우 객체 전부가 모두 삭제됨
family = null;

- 만약 family의 참조를 삭제하면, father(John)와 mother(Ann)는 도달할 수 없는 섬이 되어 전체가 메모리에서 삭제됨
Internal algorithms
- 'mark-and-sweep' : 가비지 컬렉션의 기본 알고리즘
- 가비지 컬렉터는 루트(root) 정보를 수집하고 기억(mark)
- 루트가 참조하고 있는 모든 객체를 방문하고 mark
- 모든 객체들이 참조하고 있는 객체들도 모두 mark
- 루트에서 도달 가능한 모든 객체를 방문할 때까지 반복
- mark 되지 않은 모든 객체를 메모리에서 삭제
- 다양한 최적화 기법
- generational collection(세대별 수집)
- incremental collection(점진적 수집)
- idle-itme collection(유휴 시간 수집)
- CPU가 유휴 상태일 때에만 가비지 컬렉션 실행
Object methods, "this"
Method examples
let user = {
name: "John",
age: 30
};
user.sayHi = function(){
alert("Hello");
}
- 메서드(method) : 객체 프로퍼티에 저장된 함수
- object.doSomething()
"this" in methods
sayHi(){
alert(this.name);
}
- 대부분의 메서드는 객체 프로퍼트의 값을 활용
- 메서드 내부에서 this 키워드를 사용하면 객체에 접근할 수 있음
- this는 런타임 시 결정됨, 메서드를 호출할 때 사용된 객체를 의미
"this" is not bound
let user = { name: "John" };
let admin = { name: "Admin" };
function sayHi() {
alert( this.name );
}
user.fn = sayHi;
admin.fn = sayHi;
user.fn();
admin.fn();
- 동일한 함수라도 다른 객체에서 호출한다면 'this' 값이 달라짐
- '.' 앞의 객체가 무엇인가에 따라 '자유롭게' 결정됨
- cf. 객체 없이 this 호출 시 == undefined
Arrow functions have no "this"
let user = {
firstName: "John",
sayHi() {
let arrow = () => alert(this.firstName);
arrow();
}
}
user.sayHi();
- 화살표 함수는 자신만의 this를 갖지 않음
- 화살표 함수에서 this를 참조하면 외부 함수의 this를 참조
- 외부 컨텍스트에 있는 this를 사용하려는 경우 화살표 함수 권장
Constructor, operator "new"
- 같은 타입의 (유사한) 객체를 여러 개 만들 때, 'new' 연산자와 생성자 함수 사용
Constructor function
function User(name) {
this.name = name;
this.isAdmin = false;
}
let user = new User("John");
alert(user.name);
alert(user.isAdmin);
- 생성자 함수
- 함수 이름의 첫 글자는 대문자로 시작
- 반드시 'new' 연산자를 붙여 실행
- 객체 생성 코드의 재사용성
- new Object(..) 키워드
- 빈 객체를 만들어 this에 할당
- 함수 본문 실행, this에 새로운 프로퍼티 추가하여 수정
- this 반환
Return from constructors
- 객체를 return 하면 this 대신 객체를 반환
- 원시형을 return 하면 retur문이 무시됨
Methods in constructors
- 생성자 함수를 사용하면 객체 내부를 유연성 있게 구성할 수 있음
Optional chaining '?.'
The "non-existing property" problem
- 특정 객체나 프로퍼티가 실제로 있는지 확인하기 위해 AND(&&) 사용
Optional chaining
let user = {};
alert( user?.address?.street );
- ?. 은 왼쪽(앞)의 평가 대상이 undefined나 null이면 멈추고 undefined 반환 (에러 발생하지 않음)
Short-circuiting
- 단락 평가(short-circuit) : 평가 대상에 값이 없으면 즉시 평가를 멈춤
Other variants: ?.(), ?.[]
- ?. 연산자가 아닌 특수한 문법 구조체(syntax construct)
let user1 = {
admin() {
alert("관리자 계정입니다.");
}
}
let user2 = {};
user1.admin?.();
user2.admin?.();
let user1 = {
firstName: "John"
};
let user2 = null;
let key = "firstName";
alert( user1?.[key] );
alert( user2?.[key] );
delete user?.name;
Symbol type
Symbols
- 객체 프로퍼티 키는 문자형과 심볼형만 허용
- 심볼(symbol)은 원시형 데이터로, 유일한 식별자(unique identifier)를 만들고자 할 때 사용
let id1 = Symbol("id");
let id2 = Symbol("id");
alert(id1 == id2);
- Symbol() 로 생성
- "" 설명 추가 가능
- 이름과 설명이 동일한 여러 심볼을 만들어도 모두 다른 값
- cf. 심볼은 문자형으로 자동 형 변환 되지 않음
- .toString() 또는 symbol.description 사용
"Hidden" properties
- 숨김(hidden) 프로퍼티는 외부 코드에서 접근 및 수정 불가
- 심볼을 이용하여 숨김 프로퍼티를 만들 수 있음
- Symbols in a literal
- 대괄호를 사용해 심볼형 키를 만들 수 있음
- [id] : 123
- for...in에서 심볼 배제
- Object.assign은 심볼 포함
Global symbols
- 전역 심볼 레지스트리(global symbol registry)
- Symbol.for(key)를 사용하여 동일한 심볼 개체에 접근하거나 생성할 수 있음 (전역 심볼)
- Symbol.keyFor(sym)를 사용하면 전역 심볼 레지스트리 내에서 전역 심볼의 이름을 얻어냄 (없을 경우 undefined)
System symbols
- 자바스크립트 내부에서 사용되는 심볼
- 잘 알려진 심볼(well-known symbols)
- Symbol.hasInstance
- Symbol.isConcatSpreadable
- Symbol.iterator
- Symbol.toPrimitive
Object to primitive conversion
- 객체의 형 변환 (hint)
- 객체 논리 평가 시 true, 숫자형이나 문자형으로만 형 변환
- string
- alert 같이 객체를 출력할 때 문자형으로의 형 변환
- number
- 객체끼리 연산이나 수학 관련 함수를 적용할 때 숫자형으로의 형 변환
- default
- 연산자가 기대하는 피연산자를 확신할 수 없을 때
- 형 변환 알고리즘
- 객체에 objSymbol.toPrimitive 메서드를 찾아 호출
- 없는 경우 "string"이라면
- obj.toString()이나 obj.valueOf() 호출
- "number"나 "default"라면
- obj.valueOf()나 obj.toString() 호출
"Objects: the basics", by Ilya Kantor, 2007-2022, https://javascript.info/object-basics