드림오구
article thumbnail

🌊 프로토타입 체인

: 자바스크립트 엔진의 특성상 객체의 프로퍼티에 접근할 때 해당 객체에 프로퍼티가 없으면 부모 역할을 하는 프로퍼토타입을 순차적으로 탐색한다.

 

__proto__

: 모든 객체는 __proto__ 접근자 프로퍼티를 통해 자신의 프로토타입, 즉 [[Prototype]] 내부 슬롯에 간접적으로 접근할 수 있다.

  • __proto__ 접근자 프로퍼티는 상속을 통해 사용된다.
  • __proto__ 접근자 프로퍼티를 통해 프로토타입을 접근하는 이유는 상호 참조에 의해 프로토타입 체인이 생성되는 것을 방지하기 위해서다. (프로토타입 체인은 단방향으로 구현되어야한다)
  • 모든 객체가 __proto__접근자를 사용할 수 있는 것이 아니기 때문에 __proto__ 접근자 프로퍼티를 코드 내에서 직접 사용하는 것은 권장하지 않는다.
  • 사용 목적 : 객체가 자신의 프로토타입에 접근 또는 교체하기 위해 사용

prototype 프로퍼티

: 함수 객체만이 소유하는 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킨다.

  • Object.prototype으로부터 상속받은 __proto__ 접근자 프로퍼티와 함수 객체만이 가지고 있는 prototype 프로퍼티는 결국 동일한 프로퍼티를 가진다.
  • constructor이 소유한다.
  • 사용 목적 : 생성자 함수가 자신이 생성할 객체의 프로토타입을 할당하기 위해 사용

 

프로토타입 상속 (ES5 클래스)

function Person(first, last, age, gender, interests){
    this.name = {
        first,
        last
    }
    this.age = age;
    this.gender = gender;
    this.interests = interests;
}

// Person의 메소드
Person.prototype.greeting = function() {
    alert("Hi! I'm" + this.name.first + '.');
}

// student 클래스 만들기
// 추가될 속성 학교 (초등학교, 중학교, 고등학교, 대학교)
// greeting 인사

function Student(first, last, age, gender, interests, school){
    Person.call(this, first, last, age, gender, interests);
    this.school = school;
}

Student() 생성자 함수가 Person()을 상속 받기 위해 call() 함수를 사용한다.

call() 함수의 첫번째 매개변수 this는 다른 곳에서 정의된 함수를 현재 컨텍스트에서 실행할 수 있게 하고, 나머지 실제 함수 실행에 필요한 인자들을 전달한다.

마지막 줄에 새 속성인 school을 정의하여 Student만 갖는 속성을 만들어준다.

 

→ 단, 상속 받은 Person() 생성자의 prototype 속성은 상속 받지 못한다.

 

Object.getOwnPropertyNames(Student.prototype); // ['constructor']
Object.getOwnPropertyNames(Person.prototype); // ['constructor', 'greeting']
// person의 prototype을 상속받지 못했기 때문에 Person을 상속 받는 객체를 생성하여 Student.prototype으로 할당한다
Student.prototype = Object.create(Person.prototype); 
let student = Object.getOwnPropertyNames(Student.prototype); 
console.log(student) // []


Student.prototype.constructor;
// Person을 상속받은 객체를 할당받아 아래를 반환한다.
// Person(first, last, age, gender, interests){
//     this.name = {
//         first,
//         last
//     }
//     this.age = age;
//     this.gender = gender;
//     this.interests = interests;
// }

Student.prototype.constructor = Student; 
//Student을 다시 할당해주면 Person도 상속받고 Student를 반환하는 것을 확인할 수 있다.
// Student(first, last, age, gender, interests, school){
//     Person.call(this, first, last, age, gender, interests);
//     this.school = school;
// }

Person을 상속 받는 새 객체를 생성한 후 Student.prototype에 할당한다

Sudent.prototype.constructor에 Student를 다시 할당하면 Person도 상속받고 Student를 반환하는 것을 확인할 수 있다.

 

프로토타입 상속 (ES6)

: ES6에는 클래스 문법이 새로 공개되어 조금 더 쉽고 명확하게 재활용할 수 있게 된다.

 

class Person {
    constructor(first, last, age, gender, interests){
        this.name = {
            first,
            last
        };
        this.age = age;
        this.gender = gender;
        this.interests = interests;
    
    }
    greeting(){
        console.log(`Hi! I'm ${this.name.first}`)
    }
}

let oh = new Person('Oh', 'Gu', 30, 'female', ['coding'])
oh.greeting() // Hi! I'm Oh

 

Person을 상속 받는 Student 클래스를 만들기

 

// extends로 Person을 상속받는 다는 것을 표기한다.
class Student extends Person{
    constructor(first, last, age, gender, interests, school){
        this.name = {
            first,
            last
        };
        this.age = age;
        this.gender = gender;
        this.interests = interests;

        // Student 클래스에 추가 됨
        this.school = school;
    }
}

//constructor에서 첫 번째로 super 연산자를 정의하면 코드를 조금 더 읽기 쉬워진다. 
// super() → 상위 클래스의 생성자를 호출하여 super()의 매개변수를 통해 상위 클래스의 멤버를 상속 받을 수 있는 코드

class Student extends Person{
    constructor(first, last, age, gender, interests, school){
        super(first, last, age, gender, interests);

        // Student 클래스에 추가 됨
        this.school = school;
    }
}

 

Getter와 Setter

: 생성한 클래스 인스턴스의 속성 값을 변경하거나 최종 값을 예측할 수 없을 때 getter와 setter을 사용한다. 

  • Getter : 현재 값을 반환
  • Setter : 해당 값을 변경
class Student extends Person{
    constructor(first, last, age, gender, interests, school){
        super(first, last, age, gender, interests);

        // Student 클래스에 추가 됨
        this.school = school;
    }

    get school(){
        return this.school
    };
    set school(newSchool){
        this.school = newSchool;
    }
}
profile

드림오구

@드림오구