Today I Learned

자바스크립트: 객체(1)

리꾸엘메 2022. 6. 28. 13:07

자바스크립트: 프로토타입 객체 기반의 함수형 동적 타입 스크립트

 

1. 객체(Object)

- 한 개 이상의 데이터를 담을 수 있는 자료형 (원시타입은 한 개의 데이터)

- 키: 값으로 구분된 프로퍼티를 중괄호 안에 담고 있다.

- 객체 지향 프로그래밍: 사물, 개념 등 실물로 존재하는 모든 것을 프로그래밍에서 사용하기 위해 핵심 내용이나 기능만 추상화해 정의하는 프로그래밍 패러다임, 인간이 사물을 인지하는 방식을 프로그래밍에 접목하기 위한 방법

//구기종목:
//공을 가지고 한다.
//점수로 경쟁한다.

let ballGame = new Object(); //새로운 객체를 생성하는 객체 생성자 함수 사용
ballGame = {  // 중괄호를 사용하는 객체 리터럴 문법
ball: true,
score: true,
};

- 프로퍼티를 추가, 삭제 할 수 있다. 

- 점 표기법으로 프로퍼티 값을 읽을 수 있다. 

- 프로퍼티 값에 모든 자료형이 가능하다. (불리언, 숫자 등)

//프로퍼티 값 읽기
console.log(ballGame.ball); //true
//새로운 프로퍼티 추가: 구기종목에는 트랙이 없다. 
ballGame.track = false;

- 대괄호 표기법: 변수 이름엔 공백을 사용할 수 없기 때문에 프로퍼티를 여러 단어로 만들고 싶을 때는 대괄호를 사용한다.

- 대괄호 표기법을 사용한 프로퍼티를 다시 프로퍼티 키로 사용할 수 있다. 

ballGame.specific stadium = true;
//문법에러

ballGame["specific stadium"]= true;
console.log(ballGame["specific stadium"]); //true

let stadium= "specific stadium";
console.log(ballGame[stadium]); //true

- 변수를 참조해 프로퍼티를 만들 때 변수명과 프로퍼티의 키, 값이 동일하면 축약할 수 있다. (함수는 일종의 객체이다.)

- 프로퍼티 키로 예약어를 사용할 수 있다. 심볼형에 속하지 않는 키는 문자열로 자동 변환된다. (식별자로 쓰이는 심볼형?)

- __proto__는 상속과 연관된 개념으로 값을 할당해도 무시된다. 

function makeSoccerPlayer(name, age, number) {
return {
    	category: 'soccer',
        name, //name:name에서 축약
        age, //age: age에서 축약
        for: number, //예약어를 키로 사용할 수 있다
        goals: undefined,
	};
}
let player1 = makeSoccerPlayer(messi, 35, 10);
player.__proto__= 99; //숫자를 할당했지만, 값은 객체로 나온다.

- 존재하지 않는 프로퍼티에 접근하면 에러가 아닌 undefined를 반환한다. 

- "key" in object 를 사용하는 방법도 있다. (있으면 true 없으면 false를 반환한다.)

- "key" in object를 사용하는 이유: 프로퍼티의 존재를 더 명확히 확인하기 위해

console.log(player1.position) //undefined
console.log("age" in player1) //true
console.log("position" in player1) //false
console.log(player1.goals) 
//goals프로퍼티의 값 undefined가 출력되지만 할당되지 않은 키와 구분되지 않음
//이 때 "goals" in player1 을 사용하면 프로퍼티의 유무를 확실히 확인할 수 있다.
//값이 없거나 알 수 없을 때는 주로 null을 사용하기 때문에 보통 undefined로 값을 정의하지는 않는다.

- for ... in 반복문을 사용하면 프로퍼티의 키, 값을 확인할 수 있다. 

- 정수인 프로퍼티는 자동으로 정렬된다. (입력한 순서를 유지하려면 정수 앞에 +를 붙여 정수가 아니도록 만든다.) 

for (let key in player1) { //key 대신 다른 변수명을 사용해도 된다.)
	console.log(key); //프로퍼키 키가 순서대로 출력된다.
	console.log(player1[key]);//프로퍼티의 값이 순서대로 출력된다.
}

const positionNumber = {
    5: centerDeffender,
    9: centerForward,
	1: goalKeeper,
}
for (let key in positionNumber) {
	console.log(key) // 1, 5, 9 (키를 +5, +9, +1로 지정하면 입력한 순서대로 출력된다.)

- const로 선언한 객체의 프로퍼티는 변경할 수 있을까?

가능하다. const는 할당한 변수가 변경되는 것 을 막지만 변수의 내용(프로퍼티)이 변경되는걸 막지는 않는다.


2. 객체의 복사

- 원시 타입 변수는 값을 할당할 때 값이 그대로 변수에 저장된다. 원시타입의 변수를 복사할 때도 값이 그대로 복사된다. 

- 반면 객체는 객체에 대한 참조 값이 저장되며, 객체를 복사할 때 도 객체 프로퍼티의 참조 값만 복사된다.

- 객체를 복사하면 변수는 두 개 이지만, 참조하는 객체는 하나이기 때문에 여러 변수로 객체에 접근, 조작 가능

let a = 'apple'
let b = a
console.log(a, b) // apple apple
a= 'berry'
console.log(a, b) // berry apple 
//a를 재할당해도 b의 값은 변하지 않음 

let c = {
  0:'apple',
}
let d = c
console.log(c,d) //{0:'apple'}{0:'apple'}
c[0]='berry'
console.log(c,d) //{0:'berry'}{0:'berry'}
//c의 프로퍼티에 변화가 생기면 d에도 반영된다.

 - 원시 타입 변수는 값이 같을 경우 비교할 때 true를 반환한다.

- 반면 객체는 같은 프로퍼티를 가지고 있어도 비교 시 같지 않다는 결과가 나온다.

let a = 'apple'
let b = 'apple'
console.log(a===b) // true

let c = {
  0:'apple',
}
let d = {
  0:'apple',
}
console.log(c===d) //false
d=c
console.log(c===d) //true

- 기존 객체와 같은 프로퍼티를 가지면서 독립적인 객체를 만들기 위해서는 어떻게 할까?

- 1. 새 객체를 생성 후 for...in 반복문을 활용해 기존 객체의 프로퍼티를 넣어 준다. 

- 2. Object.assign(dest, src1, src2, ...srcN)

dest는 목표로 하는 새 객체, src는 프로퍼티를 복사하려는 객체, dest를 제외한 모든 객체의 프로퍼티가 dest로 복사된다.

- 깊은복사: 객체 프로퍼티가 원시타입이 아닐 경우(다른 객체의 참조 값, 함수 등) 하위 객체도 같은 방법으로 복사해야 한다. lodash의 _.cloneDeep(obj)메서드를 사용할 수 있다.

let user = {
name: 'john',
age: 30,
}
let cloneObj = {} //새 객체 선언
for (let key in user) {
cloneObj[key]=user[key];
}
//user, cloneObj객체는 서로 다른 프로퍼티를 참조하기 때문에 한 쪽의 프로퍼티에 변화가 생겨도 다른 쪽에 반영되지 않는다.

let cloneObj2 = {
name: 'lee'
}
Object.assign(cloneObj2, user)
//마찬가지로 user의 프로퍼티가 cloneObj2객체에 복사되었다.
//프로퍼티 키가 중복일 경우 복사하려는 값으로 덮어씌운다.

3. 가비지 컬렉션

- 변수, 객체, 함수 등 생성되는 모든 것은 메모리를 차지한다. 자바스크립트 엔진의 가비지 컬렉터는 '도달 가능성'의 개념을 사용해 도달 가능성이 없는 값은 삭제해 메모리 관리를 수행한다. 

- 도달 가능성(reachability): 루트 또는 루트가 참조할 수 있는  값은 모두 도달 가능한 값이다. 

- 루트: 전역 변수, 현재 함수의 지역 변수, 매개 변수, 함수 체인에서 사용되는 변수 등

- 서로 참조하는 값이 있다고 해도, 루트에서 부터 참조할 수 없다면(루트에서 부터 도달하지 못하는 값) 삭제된다.

- mark-and-sweep: 루트가 참조하는 값을 mark하고, mark된 값에서 다시 참조하는 값을 찾아 mark하는 방식으로 더 이상 mark할 수 없을 때까지 mark과정을 반복해 mark되지 않은 값을 삭제하는 가비지 컬렉터의 메모리 관리 알고리즘 

 

let player = {
name: 'messi'
}; 
//이 시점에서 messi는 player라는 변수가 참조하는 name프로퍼티이다. 
player=null;
//player의 값이 변해 name프로퍼티를 참조하지 않기 때문에 도달할 수 없는 값으로 판단해 메모리에서 삭제한다.

- 도달 가능성이 있는 값은 삭제하지 않는다. 

let player = {
  name: 'messi'
}
let mom = player
player=null;
console.log(mom) //{name:'messi'}
console.log(player) //null

https://ko.javascript.info/object

 

객체

 

ko.javascript.info

 

 

'Today I Learned' 카테고리의 다른 글

자바스크립트: 객체2  (0) 2022.06.29
타입스크립트  (0) 2022.06.28
첫 면접  (0) 2022.06.22
React, Angular, Vue의 차이  (0) 2022.06.14
이벤트 버블링과 캡처링  (0) 2022.06.14