320x100
320x100

객체

: 하나의 데이터만 담을 수 있는 '원시형' 데이터와는 달리 여러 자료형을 담을 수 있는 데이터

: { 중괄호 }를 이용하여 선언하며 중괄호 안에는 키:값 형태의 프로퍼티로 구성

: 키에는 문자형, 값에는 모든 자료형 사용 가능

: JSON 형식으로 작성

: 프로퍼티의 값은 수정 가능

const a = {
	name: 'nemar',
    age: 20,
    friends: ['Jeniffer', 'Kaiser'],
};

console.log(a.friends);

 

 

 

대괄호 표기법

: 객체의 프로퍼티 쌍에 접근하기 위한 또 다른 방법

: a.friends 대신 a[friends]로 접근

: 해당하는 키가 없어도 오류가 발생되지 않음

: 키에 변수를 사용할 수 있음 (동적으로 사용가능)

: 문자열도 키로 사용 가능

let fruit = prompt("어떤 과일을 구매하시겠습니까?", "apple");

let bag = {
  [fruit]: 5, // 변수 fruit에서 프로퍼티 이름을 동적으로 받아 옵니다.
};

 

 

 

in 연산자

: 객체안에 프로퍼티의 존재 여부 확인 (true / false)

 

 

 

for in 반복문

: 객체에 대한 반복문

: 객체의 값에 순차적으로 접근할 수 있음

const object = {
	name: 'jamse',
    age: 30,
};

for (const key in objec) {
	console.log(key);
}

 

 

정수 프로퍼티

: 프로퍼티의 키가 정수면 자동 정렬되어 출력됨

 

 

프로퍼티 삭제

: delete obj.prop

 

 

 

메서드 단축구문

: 객체 리터럴 안에 메서드를 선언 할 때 단축하여 작성하는 방법

user = {
  sayHi() { // "sayHi: function()"과 동일합니다.
    alert("Hello");
  }
};

 

 

 

자유로운 this 사용

: 자바스크립트에서는 모든 함수에 this 사용 가능

let user = { name: "John" };
let admin = { name: "Admin" };

function sayHi() {
  alert( this.name );
}

// 별개의 객체에서 동일한 함수를 사용함
user.f = sayHi;
admin.f = sayHi;

// 'this'는 '점(.) 앞의' 객체를 참조하기 때문에
// this 값이 달라짐
user.f(); // John  (this == user)
admin.f(); // Admin  (this == admin)

admin['f'](); // Admin (점과 대괄호는 동일하게 동작함)

 

 

 

심볼형

: 유일한 식별자를 만들기 위한 자료형

: 유일성이 보장되기 때문에 값이 같아도 다른 데이터로 취급

: 암시적인 문자형 변환이 안되기 때문에 toString()을 통해 값 출력

let id1 = Symbol("id");
let id2 = Symbol("id");

alert(id1 == id2); // false

 

 

 

심볼형 키

: 키가 심볼인 경우 for in에서 제외되어 출력 (심볼형 프로퍼티 숨기기)

: 외부 스크립트나 라이브러리에서 참조 불가

let id = Symbol("id");

let user = {
  name: "John",
  [id]: 123 // "id": 123은 안됨
};

 

 

 

심볼형 키 접근하기 (ObjectAssign)

let id = Symbol("id");
let user = {
  [id]: 123
};

let clone = Object.assign({}, user);

alert( clone[id] ); // 123

 

 

 

전역 심볼

// 전역 레지스트리에서 심볼을 읽습니다.
let id = Symbol.for("id"); // 심볼이 존재하지 않으면 새로운 심볼을 만듭니다.

// 동일한 이름을 이용해 심볼을 다시 읽습니다(좀 더 멀리 떨어진 코드에서도 가능합니다).
let idAgain = Symbol.for("id");

// 두 심볼은 같습니다.
alert( id === idAgain ); // true

 

 

 

전역 심볼 찾기

let globalSymbol = Symbol.for("name");
let localSymbol = Symbol("name");

alert( Symbol.keyFor(globalSymbol) ); // name, 전역 심볼
alert( Symbol.keyFor(localSymbol) ); // undefined, 전역 심볼이 아님

alert( localSymbol.description ); // name

 

 

 

참조에 의한 객체복사

let user = { name: 'John' };

let admin = user;

admin.name = 'Pete'; // 'admin' 참조 값에 의해 변경됨

alert(user.name); // 'Pete'가 출력됨. 'user' 참조 값을 이용해 변경사항을 확인함

 

 

 

객체병합 (assign)

: 목표객체에 동일한 이름의 키가 있는 경우 덮어쓰기 됨

let user = { name: "John" };

let permissions1 = { canView: true };
let permissions2 = { canEdit: true };

// permissions1과 permissions2의 프로퍼티를 user로 복사합니다.
Object.assign(user, permissions1, permissions2);

// now user = { name: "John", canView: true, canEdit: true }

 

 

 

생성자 함수

: 유사한 객체를 여러개 만들 때 유용한 함수

: 일반함수와 구분하기 위해 첫 글자를 대문자로 작성하는 것이 관례

function User(name) {
  this.name = name;

  this.sayHi = function() {
    alert( "제 이름은 " + this.name + "입니다." );
  };
}

let bora = new User("이보라");

bora.sayHi(); // 제 이름은 이보라입니다.

 

 

 

new target

: 새로운 객체를 만든다는 것을 명시하여 유연한 코드 작성 

function User(name) {
  if (!new.target) { // new 없이 호출해도
    return new User(name); // new를 붙여줍니다.
  }

  this.name = name;
}

let bora = User("보라"); // 'new User'를 쓴 것처럼 바꿔줍니다.
alert(bora.name); // 보라

 

 

 

 

객체를 원시형으로 변환하기

- hint

: 세 종류로 구분되는 객체형의 변환의 구분 기준

: 목표로 하는 자료형 

: string, number, default

 

- default

: 연산자가 기대하는 자료형이 확실치 않은 경우

// string
// 객체를 출력하려고 함
alert(obj);

// 객체를 프로퍼티 키로 사용하고 있음
anotherObj[obj] = 123;


// number
// 명시적 형 변환
let num = Number(obj);

// (이항 덧셈 연산을 제외한) 수학 연산
let n = +obj; // 단항 덧셈 연산
let delta = date1 - date2;

// 크고 작음 비교하기
let greater = user1 > user2;


// default
// 이항 덧셈 연산은 hint로 `default`를 사용합니다.
let total = obj1 + obj2;

// obj == number 연산은 hint로 `default`를 사용합니다.
if (user == 1) { ... };

 

 

 

Synbol.toPrimtive()

: 목표로 하는 자료형을 명명하는데 사용하는 함수

let user = {
  name: "John",
  money: 1000,

  [Symbol.toPrimitive](hint) {
    alert(`hint: ${hint}`);
    return hint == "string" ? `{name: "${this.name}"}` : this.money;
  }
};

// 데모:
alert(user); // hint: string -> {name: "John"}
alert(+user); // hint: number -> 1000
alert(user + 500); // hint: default -> 1500

 

 

 

toString / ValueOf

let user = {name: "John"};

alert(user.toString()); // [object Object]
alert(user.valueOf() === user); // true
let user = {
  name: "John",
  money: 1000,

  // hint가 "string"인 경우
  toString() {
    return `{name: "${this.name}"}`;
  },

  // hint가 "number"나 "default"인 경우
  valueOf() {
    return this.money;
  }

};

alert(user); // toString -> {name: "John"}
alert(+user); // valueOf -> 1000
alert(user + 500); // valueOf -> 1500

 

 

 

추가 형 변환

let obj = {
  // 다른 메서드가 없으면 toString에서 모든 형 변환을 처리합니다.
  toString() {
    return "2";
  }
};

alert(obj * 2); // 4, 객체가 문자열 "2"로 바뀌고, 곱셈 연산 과정에서 문자열 "2"는 숫자 2로 변경됩니다.

 

 

 

가비지 컬렉션

: 쓸모가 없게 된 값을 메모리에서 삭제하는 자바스크립트 엔진의 기능

: 자바스크립트에서는 도달 가능한 (reachability) 개념을 통해 메모리 관리 수행

: 도달 가능한 값은 메모리에서 삭제되지 않음

 

- 삭제되지 않는 값 (root)

: 현재 함수의 지역변수와 매개변수

: 중첩 함수의 체인이 있는 함수에서 사용되는 변수와 매개변수 (객체가 참조하는 변수)

: 전역변수

 

 

 

 

연결된 객체

: 값을 복사하면 delete를 통해 원본 객체의 키를 제거하면 도달할 수 없는 값으로 메모리에서 삭제됨

 

 

 

내부 알고리즘

- mark and sweep

: 가비지 컬렉터는 루트(root) 정보를 수집하고 이를 ‘mark(기억)’.
: 루트가 참조하고 있는 모든 객체를 방문하고 이것들을 ‘mark’.
: mark 된 모든 객체에 방문하고 그 객체들이 참조하는 객체도 mark 수행

: 한번 방문한 객체는 전부 mark 하기 때문에 같은 객체를 다시 방문하는 일은 없음

: 루트에서 도달 가능한 모든 객체를 방문할 때까지 위 과정을 반복
: mark 되지 않은 모든 객체를 메모리에서 삭제

 

 

 

 

자바스크립트 엔진에서 사용하는 가비지 컬렉션 최적화 기법

- generational collection(세대별 수집)

: 객체를 '새로운 객체’와 '오래된 객체’로 나눔

: 객체 상당수는 생성 이후 제 역할을 빠르게 수행해 금방 쓸모가 없어지는데, 이런 객체를 '새로운 객체’로 구분

  가비지 컬렉터는 이런 객체를 공격적으로 메모리에서 제거

: 일정 시간 이상 동안 살아남은 객체는 '오래된 객체’로 분류하고, 가비지 컬렉터가 덜 감시


- incremental collection(점진적 수집)

: 방문해야 할 객체가 많다면 모든 객체를 한 번에 방문하고 mark 하는데 상당한 시간이 소모 됨

: 가비지 컬렉션에 많은 리소스가 사용되어 실행 속도가 느려짐

: 자바스크립트 엔진은 이런 현상을 개선하기 위해 가비지 컬렉션을 여러 부분으로 분리한 다음,

  각 부분을 별도로 수행

: 작업을 분리하고, 변경 사항을 추적하는 데 추가 작업이 필요하긴 하지만,

  긴 지연을 짧은 지연 여러 개로 분산시킬 수 있다는 장점 존재

 

- idle-time collection(유휴 시간 수집)

: 가비지 컬렉터는 실행에 주는 영향을 최소화하기 위해 CPU가 유휴 상태일 때에만 가비지 컬렉션을 실행

 

 

 

 

옵셔널 체이닝 ?.

: 객체의 키가 존재하지 않아도 오류를 출력하지 않도록 하는 문법 구조체 (연산자가 아님)

: 키가 null 이나 undefined일 경우 그대로 출력

: 읽기에는 사용할 수 있지만 쓰기에는 사용 불가

: delete와 연계하여 사용가능

let user = {}; // 주소 정보가 없는 사용자

alert( user?.address?.street ); // undefined, 에러가 발생하지 않습니다.

 

 

 

단락 평가

: ?.의 좌측 평가대상에 값이 없으면 평가를 멈춤

let user = null;
let x = 0;

user?.sayHi(x++); // 아무 일도 일어나지 않습니다.

alert(x); // 0, x는 증가하지 않습니다.

 

 

 

옵셔널 체이닝을 이용해 안전하게 프로퍼티를 읽는 방법

: 객체의 존재 여부가 확실치 않더라도 안전하게 프로퍼티를 읽을 수 있음

let user1 = {
  firstName: "Violet"
};

let user2 = null; // user2는 권한이 없는 사용자라고 가정해봅시다.

let key = "firstName";

alert( user1?.[key] ); // Violet
alert( user2?.[key] ); // undefined

alert( user1?.[key]?.something?.not?.existing); // undefined

 

 

 

 

 

Refference

https://ko.javascript.info/object

https://ko.javascript.info/object-methods

https://ko.javascript.info/symbol

https://ko.javascript.info/object-copy

https://ko.javascript.info/constructor-new

https://ko.javascript.info/object-toprimitive

https://ko.javascript.info/garbage-collection

https://ko.javascript.info/optional-chaining

 

 

300x250
728x90