딥다이브 10장, 11장

leewol·2023년 5월 23일
0
post-thumbnail

[10장] 객체 리터럴

자바스크립트는 프로토타입 기반 객체 지향 언어

객체

0개 이상의 프로퍼티로 구성된 집합

  • 변경 가능한 값 (mutable value)
  • 원시값을 제외한 나머지 값(함수, 배열, 정규 표현식 등)
  • 객체 타입은 다양한 타입의 값(원시값, 다른 객체)을 하나의 단위로 구성한 복합적인 자료구조
  • 상태와 동작을 하나의 단위로 구조화할 수 있어 유용

객체 지향 프로그래밍(Object Oriented Programming
객체의 집합으로 프로그램을 표현하려는 프로그래밍 패러다임

객체 리터럴에 의한 객체 생성

가장 간단하고 일반적인 객체 생성 방법

  • 중괄호({}) 내에 0개 이상의 프로퍼티 정의
  • 객체 리터럴을 값으로 평가되는 표현식
  • 변수에 할당되는 시점에, 자바스크립트 엔진은 객체 리터럴을 해석해 객체 생성

자바스크립트 객체 생성 방법

  1. 객체 리터럴

  2. Object 생성자 함수

  3. 생성자 함수

  4. Object.create 메서드

  5. 클래스 (ES6)

리터럴(literal)
사람이 이해할 수 있는 문자 또는 약속된 기호를 사용하여 값을 생성하는 표기법

인스턴스

클래스에 의해 생성되어 메모리에 저장된 실체

클래스

인스턴스를 생성하기 위한 템플릿 역할

프로퍼티

keyvalue로 구성되는, 객체의 상태를 나타내는

key

빈 문자열을 포함하는 문자열 또는 심벌

  • 식별자 역할
  • 식별자 네이밍 규칙을 따르지 않는 이름에는 반드시 따옴표를 사용
  • 대괄호 표기법 또는 마침표 표기법으로 동적 생성 가능
  • 문자열, 심벌 값 외 값을 사용하면 문자열로 암묵적 타입 변환
  • 이미 존재하는 프로퍼티 키를 중복 선언하면 덮어쓴다 ==> 프로퍼티 값 갱신

value

자바스크립트에서 사용할 수 있는 모든 값

  • 일급 객체함수도 포함
    • 프로퍼티 값이 함수인 경우, 일반 함수와 구분하기 위해 메서드(method)라 부름

프로퍼티 접근

  1. 마침표 표기법 : 마침표 프로퍼티 접근 연산자(.)

  2. 대괄호 표기법 : 대괄호 프로퍼티 접근 연산자([키])

    • 따옴표로 감싸 주지 않으면 식별자로 해석
    • 프로퍼티 키가 숫자로 이뤄진 문자열인 경우 따옴표 생략 가능
  • 객체에 존재하지 않는 프로퍼티에 접근하면 undefined 반환

프로퍼티 삭제

delete 연산자 사용

  • 존재하지 않는 프로퍼티 삭제 시 에러 없이 무시됨

메서드

객체에 묶여 있는 함수

  • 프로퍼티(상태 데이터)를 참조하고 조작할 수 있는 동작
  • 메서드 내부에서 사용한 this 키워드는 객체 자신을 가리키는 참조 변수

ES6에서 추가된 객체 리터럴 확장 기능

프로퍼티 축약 표현

변수 이름과 프로퍼티 키가 동일할 때 프로퍼티 키 생략 가능

// ES6
let x = 1, y = 2;
const obj = { x, y };

// ES5
var x = 1, y = 2;
var obj = {
  x: x,
  y: y,
};

계산된 프로퍼티 이름

// ES6
const prefix = 'prop';
let i = 0;

// 객체 리터럴 내부에서 계산된 프로퍼티 이름으로 동적 생성
const obj = {
	obj[`${prefix}-${++i}`]: i,
	obj[`${prefix}-${++i}`]: i,
	obj[`${prefix}-${++i}`]: i
};

// ES5
var prefix = 'prop';
var i = 0;
var obj = {};

obj[prefix + '-' + ++i] = i;
obj[prefix + '-' + ++i] = i;
obj[prefix + '-' + ++i] = i;

console.log(obj); // { prop-1: 1, prop-2: 2, prop-3: 3 }

메서드 축약 표현

메서드 축약 표현으로 정의한 메서드는 프로퍼티에 할당한 함수와 다르게 동작

// ES6
const obj = {
  name: 'Lee',
  // 메서드 축약
  sayHi() {
    console.log('Hi! ' + this.name);
  }
};

// ES5
var obj = {
  name: 'Lee',
  sayHi: function() {
    console.log('Hi! ' + this.name);
  }
};

obj.sayHi(); // Hi! Lee

[11장] 원시값과 객체의 비교

원시 타입 값객체 타입 값
변경변경 불가능한 값(immutable value)변경 가능한 값(mutable value)
할당변수에 실제 값 저장변수에 참조 값 저장
다른 변수에 할당 시원본의 원시 값 복사(값에 의한 전달, pass by value)원본의 참조 값 복사(참조에 의한 전달, pass by reference)

원시 값

변경 불가능한 값

한번 생성된 원시 값은 읽기 전용 값으로서 변경할 수 없음 (불변성)

  • 데이터의 신뢰성 보장
  • 변경 불가능하다는 것은 변수가 아니라 에 대한 것
  • 변수는 언제든지 재할당을 통해 변수 값을 변경(교체)할 수 있음

변수
하나의 값을 저장하기 위해 확보한 메모리 공간 자체, 혹은 그 메모리 공간을 식별하기 위해 붙인 이름


변수에 저장된 데이터로서, 표현식이 평가되어 생성된 결과

상수
재할당이 금지된 변수 (변경 불가능한 값과 다름)

원시 값을 할당한 변수에 새로운 원시 값을 재할당하면, 메모리 공간에 저장되어 있는 재할당 이전의 원시 값을 변경하는 것이 아니다. (원시 값은 변경 불가능한 값이므로) 새로운 메모리 공간을 확보하고 재할당한 원시 값을 저장한 후, 변수는 새롭게 재할당한 원시 값을 가리킨다. 이때 변수가 참조하던 메모리 공간의 주소가 바뀐다.

문자열과 불변성

문자열

0개 이상의 문자로 이루어진 집합

  • 1개의 문자는 2 byte 메모리 공간에 저장
  • 숫자는 1도, 1000000도 동일한 8 byte가 필요하지만 문자열은 길이에 따라 다름
  • 유사 배열 객체이며, 이터러블

유사 배열 객체
배열처럼 인덱스로 프로퍼티 값에 접근할 수 있고, length 프로퍼티를 갖는 객체
for 문으로 순회도 가능

var str = 'string';
str[0] = 'S';

console.log(str); // string - 문자열은 원시 값이므로 변경 X

값에 의한 전달

변수에 원시 값을 가지는 변수를 할당하면, 할당받는 변수에는 할당되는 변수의 원시 값복사되어 전달 (둘은 다른 메모리 공간에 저장된 별개 값)

  • 엄격하게 표현하면 변수에는 메모리 주소가 전달
    • 변수와 같은 식별자는 값이 아니라 메모리 주소를 기억
  • 어느 한쪽에서 재할당으로 값을 변경하더라도 서로 간섭할 수 없음

식별자
메모리 주소에 붙인 이름

객체

  • 자바스크립트 객체는 해시 테이블과 유사하지만 높은 성능을 위해 일반적인 해시 테이블보다 나은 방법으로 객체 구현
    • 클래스 없이 객체 생성 가능
    • 객체 생성 이후에도 동적으로 프로퍼티/메서드 추가 가능
    • 사용은 편리하나, 클래스 기반 OOP 언어 객체보다 프로퍼티 생성과 접근 면에서 비효율적
    • 따라서 V8 자바스크립트 엔진에서는 히든 클래스 방식으로 성능 개선

변경 가능한 값

참조 값
생성된 객체가 저장된 메모리 공간 주소 그 자체

  • 원시 값을 할당한 변수는 "변수는 ~값을 갖는다" 또는 "변수의 값은 ~다"라고 표현하는 반면,
    객체를 할당한 변수의 경우 "변수는 객체를 참조하고 있다" 또는 "변수는 객체를 가리키고 있다"라고 표현
  • 객체를 할당한 변수는 재할당 없이 객체 직접 변경 가능 (메모리에 저장된 객체 직접 수정)
    • 따라서 참조 값 변경되지 않음
    • 메모리 사용의 효율성과 성능을 위함
  • 여러 개의 식별자가 하나의 객체를 공유할 수 있다는 부작용 발생

얕은 복사와 깊은 복사

얕은 복사(shallow copy)
한 단계까지만 복사 (참조 값 복사)

깊은 복사(deep copy)
객체에 중첩되어 있는 객체까지 모두 복사 (원시 값처럼 완전한 복사본 생성)

  • 두 복사 방법 모두 원본과 다른 객체 생성
  • 원시 값을 할당한 변수를 다른 변수에 할당하는 것을 깊은 복사, 객체를 할당한 변수를 다른 변수에 할당하는 것을 얕은 복사라고 부르는 경우도 있음
// 얕은 복사
const o = { x: { y: 1 } };
const c1 = { ...o };

console.log(c1 === o); // false
console.log(c1.x === o.x); // true

참조에 의한 전달

객체를 가리키는 변수를 다른 변수에 할당하면, 원본의 참조 값복사되어 전달

  • 저장된 메모리 주소는 다르지만 동일한 참조 값 가진다, 즉 두 개의 식별자가 하나의 객체 공유
  • 따라서 어느 한쪽에서 객체를 변경(프로퍼티 추가, 수정, 삭제)하면 서로 영향을 주고받음

값에 의한 전달과 참조에 의한 전달 모두 값을 복사해서 전달하는데, 변수에 저장된 값이 원시 값이냐 참조 값이냐에 차이가 있음

  • 자바스크립트에는 값에 의한 전달만 존재한다고 말할 수 있음
profile
간살간죽 개살개죽

0개의 댓글