티스토리 뷰

이 글은 Opentutorials.org의 생활코딩 Javascript 객체 지향 프로그래밍을 수강한 후 정리한 내용입니다.

 

객체에 접근하기

const member = {
    developer : 'kim',
    designer : 'lee',
    CEO : 'park'
};
  • 점표기법 : member.developer
  • 괄호표기법 : member['developer']
  • (참고) 객체 삭제하기 : delete member.developer , 실행 결과에 따라 true 또는 false 반환

 

(참고) var, let, const

var

  • 같은 이름으로 재선언 가능
  • 선언과 초기화를 한 번에 함
  • 관리가 어려움

let

  • ES6부터 이용 가능
  • 재선언 불가능, 재할당 가능
  • 선언 이전에 참조 불가(초기화되기 전까지 Temparal Dead Zone에 위치함)
  • 선언과 초기화를 따로 함

const

  • ES6부터 이용 가능
  • 재선언 불가능, 재할당 불가능
  • 선언 이전에 참조 불가(초기화 되기 전까지 Temparal Dead Zone에 위치함)
  • 선언과 동시에 할당해야 함
  • 함수나 객체를 const로 선언하면 해당 자료형을 유지함. 식별자나 프로퍼티명으로 접근하여 값을 변경하는 것은 가능함

 

객체 조회하기

for(let position in member) {
    console.log(position, member[position]);    // 이 경우 점 표기법은 사용할 수 없다
}
// 실행결과
developer kim
designer lee
CEO park

 

내장객체 Math

Math.PI;            // 3.141592653589793
Math.random();      // 0이상 1미만 부동소숫점 의사 난수 반환
Math.floor(3.9);    // 3(버림)

 

this

JavaScript에서 전역 스크립트나 함수가 실행될 때 실행문맥(Excution Context)이 생성된다. (실제 실행은 브라우저 내의 stack에 올라가서 실행됨) 모든 context에는 참조하고 있는 객체(thidBinding)가 존재하며, 이를 알기위해 this를 사용할 수 있다.

  • 객체 내에서 this는 그 객체 자신을 가리킴
  • bind(), call(), apply()를 사용하여 this를 조작할 수 있음
const person = {
    name: 'kim',
    first: 10,
    second: 20,
    sum: function(f, s) {
        return this.first + this.second;
    }
}

console.log(person.sum());        // 30

 

constructor function

constructor는 class내에서 객체를 생성하고 초기화하기 위한 특별한 메서드이다. Javascript의 모든 객체는 constructor라는 프로퍼티를 가지며 객체의 constructor자기 자신을 만든 함수를 가리킨다.

예시 1

function Person(name, age) {
    this.name = name;
    this.age = age;
    this.getInfo = function() {...};
}

const person1 = new Person('kim', 25);   

위와 같은 방식으로 100개의 객체를 생성한다면 완벽히 똑같은 동작을 하는 getInfo함수가 100개 생성될 것이다. 어떻게 개선할 수 있을까?

예시 2 - prototype

function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.getInfo = function() {...};

const person1 = new Person('kim', 25); 

Person 객체를 만들면 내부적으로 Person을 constructor로 가지는 Person.peototype이라는 객체가 생겨난다. 이곳에 getInfo라는 함수를 만들어두면 Person을 이용하여 생성한 모든 객체가 하나의 Person.peototype를 참조하여 getInfo를 이용할 수 있게 된다. 결과적으로 getInfo가 중복해서 생성되는 문제가 해결된다. (prototype에 대한 더 자세한 설명은 아래에 계속)

 

class

class는 객체를 만드는 공장

각 사람의 이름과 첫 번째, 두 번째 점수를 저장하고 총점을 반환하는 메서드를 가진 클래스를 만들었다. Java의 클래스와 비슷한 모습이다.

class Person {
    // 생성자
    constructor(name, first, second) {
        this.name = name;
        this.first = first;
        this.second = second;
    }
    
    // 메소드
    sum() {    
        return this.first + this.second;
    }
}

 

상속과 super

만약 일부 몇 명만 세 번째 점수를 기록해야 할 필요가 생기면 어떻게 해야 할까? 기존에 작성한 Person을 상속받는 자식 클래스에서 super를 사용하면 부모 클래스인 Person의 작업을 가져올 수 있다.

class PersonPlus extends Person {
    constructor(name, first, second, third) {
        super(name, first, third);
        this.third = third;
    }
    
    sum() {
        return super.sum() + this.third;
    }
    
    // PersonPlus만의 새로운 메소드를 만들 수도 있다!
    avg() {
        return (this.first + this.second + this.third) / 3;
    }
}

Java와 같은 객체지향 언어에서는 super class의 기능을 물려받기 위해서는 sub class가 super class의 자식이 된다. 이후 sub class를 통해 어떤 객체를 만들면 그 객체가 어떤 기능을 가질 것인지는 super class와 sub class에 의해 즉 class단에서 결정된다. 생성된 객체는 이후 다른 클래스를 상속받거나 할 수 없다. 하지만 Javascript의 상속은 이와 같지 않다.

부모객체와 자식객체의 관계

Java에서 상속은 클래스 사이의 일이었다면 Javascript에서는 sub객체가 super객체의 기능을 직접 상속받을 수 있다. 또한 상속관계의 두 객체 사이의 prototype link를 수정하면 객체 생성 이후에 상속관계를 변경하는 것도 가능하다. 이때, sub객체의 prototype link가 가리키는 객체를 prototype object라고 한다.

 

객체 간 상속

__proto__

const superObj = {superVal: 'super'};

const subObj = {subVal: 'sub'};
subObj.__proto__ = superObj;

__proto__를 이용하면 객체 간에 직접 상속을 구현할 수 있다. 모든 객체는 생성될 때 __proto__속성을 가지며, 이는 객체가 생성될 때 조상이었던 함수의 prototype object를 가리킨다. 따라서 subObj.__proto__ = superObj;subObj의 prototype link가 superObj를 향하게 즉 상속을 받게 한다.

하지만 __proto__는 대부분 지원하긴 하나 표준은 아니다. Javascript에서 표준으로 인정하는 방법은 아래와 같다.

 

Object.create()

const superObj = {superVal: 'super'};

const subObj = Object.create(superObj);
subObj.subVal = 'sub';

이는 위의 __proto__를 이용한 코드와 같은 기능을 한다.

 

prototype / __proto__

// 1
function Person(name, first, second) {
    this.name = name;
    this.first = first;
    this.second = second;
}

// 2
Person.prototype.sum = function() {
    return this.first + this.second;
}

// 3
const kim = new Person('kim', 10, 20);
const lee = new Person('lee', 10, 10);

// 4(① -> ② -> ③)
console.log("kim.sum()", kim.sum());

Prototype Chain

1

Person 객체를 만들면 내부적으로 Person의 prototype객체(Person's Prototype)가 함께 만들어진다. Person객체의 prototype은 Person's Prototype를 가리키고, Person's Prototype의 constructor는 Person객체를 가리 킨다. 이때, Person's Prototype의 __proto__는 최상위 객체인 Object(Javascript 기본 요소)의 Prototype을 가리킨다. 이처럼 __proto__를 통해 상위 객체로 연결되는 구조를 Prototype Chain이라고 한다.

2

Person을 이용해 새로운 객체를 생성할 때마다 중복된 sum함수가 생성되는 것을 방지하기 위해 Person's Prototype에 sum함수를 만든다. 이때, sum함수는 Constructor Function이다.

3

new키워드를 이용하여 객체를 생성한다.

4

new Person()을 이용하여 생성한 객체kim에서 sum함수를 호출하면 어떤 일이 일어날까?

① 우선 kim객체에 sum함수가 존재하는지 확인한다.
② 존재하지 않는다면 __proto__를 통해 상위 객체로 이동한다.
③ sum함수가 존재하는지 확인한다 -> 함수를 찾았다!

이와 같이 상위 객체로 이동하며 해당 함수가 존재하는지 찾는다. 만약 최상위 객체까지 이동했는데도 해당 함수를 찾지 못한다면 오류가 발생한다.

 

 


참고 사이트

 

댓글