221105 TIL | 객체 리터럴 확장 기능

오늘 한 일

  • JavaScript의 객체와 객체 리터럴 확장 기능 정리

자바스크립트는 객체 기반의 프로그래밍 언어이며, 자바스크립트를 구성하는 대부분의 것이 객체이다. 원시 타입(Primitives)을 제외한 나머지 값들(함수, 배열, 정규표현식 등)은 모두 객체라고 할 수 있다.

자바스크립트의 객체는 키(key)와 값(value)로 이루어진 프로퍼티로 구성된 집합이다.

프로퍼티의 값으로 모든 값을 사용할 수 있는데 자바스크립트의 함수는 모두 일급 객체이므로 함수 또한 값으로 취급할 수 있다. 프로퍼티의 값이 함수일 경우 일반 함수와 구분하기 위해 메서드라고 부른다.

  • 모던 자바스크립트 Deep Dive p.124

Untitled

이처럼 객체는 프로퍼티와 메서드로 구성된 집합체다.

  • 프로퍼티 : 객체의 상태를 나타내는 값(data)
  • 메서드 : 프로퍼티(상태 데이터)를 참조하고 조작할 수 있는 동작(behavior)

객체 생성

Java나 C++ 같은 클래스 기반 객체지향 언어는 클래스를 사전에 정의하고 new 연산자와 함께 생성자를 호출하여 인스턴스를 생성하는 방식으로 객체를 생성한다.

자바스크립트는 프로토타입 기반 객체지향 언어로써 클래스 개념이 없지만 강력한 객체 지향 프로그래밍 능력을 가지고 있으며 다양한 방법으로 객체를 생성할 수 있다.

  • 객체 리터럴
  • Object() 생성자 함수
  • 생성자 함수

객체 리터럴 생성 방식 {..}

var person = {
  name: "Lee",
  sayHello: function () {
    console.log(`Hello! My name is ${this.name}.`);
  },
};

console.log(typeof person); // object
console.log(person); // {name: 'Lee', sayHello: ƒ}

new 연산자 생성 방식 new object();

const person = new Object();
person.name = "Kim";
console.log(person); // {name: 'Kim'}

생성자 함수

// 생성자 함수(Constructor)
function Person(name) {
  // 프로퍼티
  this.name = name;

  // 메소드
  this.setName = function (name) {
    this.name = name;
  };

  // 메소드
  this.getName = function () {
    return this.name;
  };
}

// 인스턴스의 생성
var me = new Person("Lee");
console.log(me.getName()); // Lee

// 메소드 호출
me.setName("Kim");
console.log(me.getName()); // Kim

프로퍼티 접근 방법

  1. dot notation(마침표 표기법) .속성명
  2. bracket notation(대괄호 표기법) [속성명문자열]
var person = {
  name: "Lee",
};

// 마침표 표기법에 의한 접근 방법
console.log(person.name); // Lee

// 대괄호 표기법에 의한 접근 방법
console.log(person["name"]); // Lee
  • 계산된 프로퍼티 이름 ES6 문법 문자열 혹은 문자열로 타입 변환할 수 있는 값으로 평가되는 표현식을 이용하여 프로퍼티 키를 동적으로 생성할 수 있다. 단, 프로퍼티 키로 사용할 표현식을 대괄호[…]로 묶어야 한다. 이를 계산된 프로퍼티 이름(Computed Property Name) 이라고 한다. ES5 문법의 경우 프로퍼티 키를 동적으로 사용하기 위해서는 객체 리터럴 외부에서 대괄호 표기법을 사용해야 한다.
    // 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에서는 객체 리터럴 내부에서도 프로퍼티 키를 동적으로 생성할 수 있다.

    // ES6
    const prefix = "prop";
    let i = 0;
    
    const obj = {
      [`${prefix}-${++i}`]: i,
      [`${prefix}-${++i}`]: i,
      [`${prefix}-${++i}`]: i,
    };
    
    console.log(obj); // {prop-1: 1, prop-2: 2, prop-3: 3}
    
  • 메소드 축약 표현 ES6 문법 ES5에서 메소드를 선언하려면 프로퍼티 값으로 함수 선언식을 할당한다.
    // ES5
    var obj = {
      name: "Lee",
      sayHi: function () {
        console.log("Hi! " + this.name);
      },
    };
    
    obj.sayHi(); // Hi! Lee
    

    ES6에서는 메소드를 선언할 때, function 키워드를 생략한 축약 표현을 사용할 수 있다.

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

프로퍼티 동적 생성

존재하지 않는 프로퍼티에 값을 할당하면 동적으로 생성된다.

var person = {
  name: "Lee",
};

person.name = "Kim";
console.log(person); // {name: 'Kim'}

프로퍼티 삭제

delete 연산자를 이용하여 객체의 프로퍼티를 삭제할 수 있다.

연산자를 이용해서 존재하지 않는 프로퍼티를 삭제하면 아무런 에러 없이 무시된다.

var person = {
  name: "Lee",
};

person.age = 20;

// age 프로퍼티가 존재하기 때문에 삭제된다
delete person.age;
// address 프로퍼티가 존재하지 않아서 삭제되지 않고, 에러도 발생하지 않는다.
delete person.address;

console.log(person); //{name: 'Lee'}

proto프로퍼티에 의한 상속

ES5에서 객체 리터럴을 상속하기 위해서는 Object.create() 함수를 사용한다. 이를 프로토타입 패턴 상속이라고 한다.

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

// 프로토타입 패턴 상속
// create 함수의 인자는 객체이다.
var child = Object.create(parent);
child.name = "child";

parent.sayHi(); // Hi! parent
child.sayHi(); // Hi! child

Untitled

ES6에서는 객체 리터럴 내부에서 proto프로퍼티를 직접 설정할 수 있다. 이것은 객체 리터럴에 의해 생성된 객체의 proto 프로퍼티에 다른 객체를 직접 바인딩하여 상속을 표현할 수 있음을 의미한다.

// ES6
const parent = {
  name: "parent",
  sayHi() {
    console.log("Hi! " + this.name);
  },
};

const child = {
  // child 객체의 프로토타입 객체에 parent 객체를 바인딩하여 상속을 구현한다.
  __proto__: parent,
  name: "child",
};

parent.sayHi(); // Hi! parent
child.sayHi(); // Hi! child