[JS] Object (ver. basic)

suuhyeony·2022년 11월 3일
0

crack JavaScript

목록 보기
8/18
post-thumbnail

객체 (Object)

원시 값을 제외한 나머지 값 (함수, 배열, 정규 표현식 등).
0개 이상의 프로퍼티와 메서드로 구성된 집합으로, 프로퍼티는 key(식별자로 일반적으로는 문자열을 사용)와 value로 구성된다.
객체 타입은 다양한 타입의 값을 하나의 단위로 구성한 복합적인 자료구조.
원시 값은 변경 불가능(immutable)한 값이지만, 객체는 변경 가능(mutable)한 값이다.

const person = {  // 프로퍼티의 집합으로 이루어진 person 객체
  name: 'dotgae',  // (key는 name, value는 'dotgae'인 프로퍼티)
  age: 20  // (key는 age, value는 20인 프로퍼티)
};

const counter = {
  num: 0,
  increase: function () {  // 프로퍼티 값이 함수일 경우, 일반함수와 구분하기 위해 **method**(객체에 묶여있는 함수)라고 부름
    this.num++;  // **메서드 내부의 this는 객체 자신(counter)을 가리키는 참조변수**
  }
};

person['sex'] = 'female';  // 동적으로 프로퍼티 키 생성 및 추가
person['name'] = 'park'; // 이미 존재하는 프로퍼티 키를 중복 선언하면, 나중에 선언한 값으로 덮어씌워진다.

// 프로퍼티 접근 방법
console.log(person.name);  // 'park'
console.log(person['age']);  // 20
console.log(person.address);  // 객체에 존재하지 않는 프로퍼티에 접근하면 undefined를 반환하며, ReferenceError가 발생하지 않는다.
delete person.sex;  // 특정 프로퍼티 삭제. 없는 프로퍼티를 삭제하면 무시됨.

// es6 확장 기능
let width = 300, height = 600;
// 1) 프로퍼티 축약 표현 가능
const obj = { width, height };
console.log(obj);  // { width: 300, height: 600 }

// 2) 계산된 프로퍼티 이름으로 프로퍼티 동적 생성 가능
const prefix = 'prop';
let i = 0;
obj[prefix + '-' + ++i] = i;  // prop-1: 1
obj[prefix + '-' + ++i] = i;  // prop-2: 2

// 3) 메서드 축약 표현 가능
const video = {
  name: 'short',
  create() {
    // ... 
  }
};
  • 프로퍼티: 객체의 상태를 나타내는 값 (data)
  • 메서드: 프로퍼티(상태 데이터)를 참조하고 조작할 수 있는 동작 (behavior)

=> 객체는 상태 데이터와 이를 참조/조작할 수 있는 메서드를 모두 포함할 수 있어 상태와 동작을 하나의 단위로 구조화하기 용이하다.


객체 생성

  • 인스턴스(클래스에 의해 생성되어 메모리에 저장된 실체) 생성 방식
    : 클래스(class: 인스턴스를 생성하기 위한 템플릿)를 사전에 정의하고, 필요한 시점에 new 연산자와 함께 생성자(constructor)를 호출해 인스턴스를 생성하여 객체를 생성하는 방식으로, 클래스 기반 객체지향 언어(ex. java, C++)에서 사용한다.
  • javaScript는 프로토타입 기반 객체지향 언어로서, 클래스 기반 객체지향 언어와는 달리, 다양한 객체 생성 방법을 지원.
  • 객체 리터럴(약속된 문법)
const person = {
  name: 'dotgae',
  sayHi: function () {
    console.log(`hi, my name is ${this.name}`);
  }
};
console.log(typeof person);  // object
console.log(person);  // { name: 'dotgae', sayHi: f }

이 외의 방식은 함수를 공부한 뒤 살펴보자.

  • Object 생성자 함수
  • 생성자 함수
  • Object.create 메서드
  • 클래스(ES6)

원시 값과 객체의 비교


1) 원시 타입(primitive type)

변경 불가능(immutable)한 값.

  • 원시 값을 변수에 할당하면 변수(메모리 공간)에는 실제 값이 저장됨.
  • 원시 값을 가진 변수를 다른 변수에 할당하면, 원본의 원시 값이 복사되어 전달되며, 새로운 메모리 공간을 확보. (값에 의한 전달 =pass by value)

*참고
: 변경 불가능/가능에 대한 내용은 변수가 아니라 값에 대한 설명임.

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

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

  • 상수 - 재할당이 금지된 변수. 상수는 단 한 번만 할당이 허용되므로 변수 값을 변경할 수 없다.

  • 원시 값 저장을 위해 확보해야 하는 메모리 공간의 크기가 정해져 있다.

    • 문자열 타입 - 1개의 문자는 2바이트의 메모리 공간에 저장 (문자열이 늘어날수록 필요 공간 커짐)
    • 숫자 타입 - 모두 동일하게 8바이트가 필요
    • 이외의 원시 타입은 크기가 명확히 규정되어 있지 않음.

// 1) 문자열과 불변성
const str = 'string';
console.log(str[0]);  // s (문자열은 유사 배열이므로 배열처럼 인덱스로 각 문자에 접근 가능)
str[0] = 'g';
console.log(str);  // string (문자열은 원시 값, 읽기 전용이므로 변경할 수 없다. 에러 발생하지 않음) 
console.log(str.length);  // 6 (원시 값을 객체처럼 사용하면 원시값을 감싸는 래퍼 객체로 자동 변환됨)
console.log(str.toUpperCase());  // STRING

// 2) 값에 의한 전달
let score = 80;
const copy = score;  // 80 이라는 **원시 값이 복사되어 전달.** 값은 동일하나, 서로 다른 메모리 공간에 저장된 별개의 값.
console.log(score, copy);  // 80 80
console.log(score === copy);  // true
score = 100; 
console.log(score);  // 100
console.log(copy);  // 80 (score 값을 변경해도 copy와는 별도의 값이므로 영향/간섭을 주지 않음)

2) 객체 타입(object/reference type)

변경 가능(mutable)한 값.

  • 객체를 변수에 할당하변 변수에는 참조 값이 저장됨.
  • 객체를 가리키는 변수를 다른 변수에 할당하면, 원본의 참조 값이 복사되어 전달됨. (참조에 의한 전달 =pass by reference)
  • 객체는 프로퍼티의 개수가 정해져 있지 않고, 값에도 제약이 없어 메모리 공간 크기를 사전 정의할 수 없다.
  • javascript 객체의 관리 방식
    • 프로퍼티 키를 인덱스로 사용하는 hash table로 관리.
    • 클래스 기반 객체지향 프로그래밍 언어에서는 사전 정의된 클래스로 객체를 생성하며, 생성 이후 프로퍼티 삭제/추가 불가.
    • javascript는 위와 달리 사전정의 필요 없이 동적으로 프로퍼티/메서드 추가/삭제가 가능하여 접근 비용이 더 많이드는 비효율적 방식임.
    • 따라서 V8 엔진에서는 프로퍼티 접근을 위해 동적 탐색 대신 hidden class라는 방식을 사용해 성능 보장.
profile
울보 개발자(멍.. 하고 울어요)

0개의 댓글