Prototype

MINIMI·2023년 2월 8일

JavaScript(Core : 기본)

목록 보기
7/10
post-thumbnail

7-1. Inheritance

1)[[Prototype]]

  • obj라는 객체에 name이라는 프로퍼티만 있고 age라는 프로퍼티는 없을 때, obj.age를 호출하면 [[Prototype]]이 참조하고 있는 prototype object에서 age라는 프로퍼티를 찾아서 참조한다
  • proto
    • [[Prototype]]의 getter, setter
    • 요즘에는 잘 사용하지 않음
    • 값은 객체 또는 null만 가능하며 다른 자료형은 무시
  • 프로토타입에서 상속 받은 프로퍼티를 상속 프로퍼티라고 한다.
const user = {
    activate : true,
    login : function(){
        console.log('로그인 되었습니다.');
    }
};

const student = {
    passion : true
};

student.__proto__ = user;

console.log(student.activate);
student.login();
console.log(student.passion);

// => "student의 프로토타입은 user이다." 또는 "student는 user를 상속 받는다"

// 프로토타입 체인
const greedyStudent = {
    class : 11,
    __proto__ : student
};

console.log(greedyStudent.activate);    //user에서 상속 받은 프로퍼티
console.log(greedyStudent.passion);     //student에서 상속 받은 프로퍼티
  • 프로토타입 체인

2) prototype feature

  • 프로토타입 특징
  • 프로토타입은 읽어오는 것만 가능하고, 추가 삭제는 불가능
    • 프로토 타입은 프로퍼티를 읽을 때만 사용하며 프로퍼티 추가, 수정, 삭제 연산은 객체에 직접 한다.
const user = {
    id : 'user',
    login(){
        console.log(`${this.id}님 로그인 되셨습니다`);
    }
};

const student = {
    __proto__ : user
};

student.id = 'user01';

student.login(); //user01님 로그인 되셨습니다.
  • this는 언제나 . 앞에 있는 객체를 의미한다.
  • for in 반복문은 상속 프로퍼티도 순회 대상에 포함시킨다.
for(let key in student){
    // id는 student의 id, login은 user의 login()
    console.log(key);

    // key에 대응하는 프로퍼티가 상속 프로퍼티가 아니라 객체에 직접 구현 된 프로퍼티일 경우 true 반환
    let isOwn = student.hasOwnProperty(key);

    if(isOwn) console.log(`객체 자신의 property : ${key}`);
  //객체 자신의 property : id
    else console.log(`상속 property : ${key}`);
  //상속 property : login    
}
  • hasOwnProperty
    • key에 대응하는 프로퍼티가 상속 프로퍼티가 아니고 obj에 직접 구현되어있는 프로퍼티일 때만 true를 반환한다.

7-2. Function Prototype

1) object constructor prototype

  • 생성자 함수 프로토타입
  • new 연산자를 사용해 만든 객체는 생성자 함수의 프로토타입 정보를 사용해 [[Prototype]]을 설정한다.

const user = {
    activate : true,
    login(){
       console.log('로그인 되었습니다.');
    }
};

function Student(name){
    this.name = name;
}

// 여기서의 prototype은 앞에서 배운 프로토타입(__proto__)과 이름만 같을 뿐 실제로는 일반 프로퍼티이다.
Student.prototype = user;

// F.prototype은 new Function을 호출할 때만 사용된다.
// new F를 호출할 때 만들어지는 새로운 객체의 [[Prototype]]을 할당한다.
// student.__proto__ == user
let student = new Student('홍길동');
let student2 = new Student('유관순');

console.log(student.activate);
student2.login();
  • Function.prototype은 new Function을 호출할 때만 사용된다.
    • new Function을 호출할 때 만들어지는 새로운 객체의 [[Prototype]]을 할당한다.

2) function prototype and conostructor property

  • 함수의 디폴트 프로퍼티 프로토타입과 constructor 프로퍼티
  • 개발자가 특별히 할당하지 않아도 모든 함수는 기본적으로 "property" 프로퍼티를 갖는다
  • 디폴트 프로퍼티 "property"는 constructor 프로퍼티 하나만 있는 객체를 가리킨다.
    • 여기서 constructor 프로퍼티는 함수 자신을 가리킨다.
  • 함수를 만들기만 해도 디폴트 프로퍼티인 prototype이 설정된다.
function Student(){}

console.log(Student.prototype.constructor);
console.log(Student.prototype.constructor == Student);

let student = new Student();    //{ constructor : Student }를 상속 받음
console.log(student.constructor == Student);

7-3. Built In Object Prototype

1) object prototype

  • Object는 내장 객체 생성자 함수인데 이 생성자 함수의 prototype은 toString을 비롯 다양한 메소드가 구현 된 거대한 객체를 참조한다.
  • new Object(), {}를 사용해 객체를 만들 때 만들어진 객체의 [[Prototype0]]은 Object.prototype을 참조한다.
const obj = {};
console.log(obj.__proto__ === Object.prototype);
console.log(obj.toString === obj.__proto__.toString);
console.log(obj.toString === Object.prototype.toString);

2) built in object prototype

  • Function, String, Number를 비롯한 내장 객체들 역시 프로토타입에 메서드를 저장한다.
  • 모든 내장 프로토타입 상속 트리 꼭대기에는 Object.prototype이 있어야 한다고 규정한다.
  • Number에도 toStrinig이 정의 되어 있고, Object에도 toString이 정의 되어 있다.
    • 중복 메서드가 있는 경우 체인에서 가까운 메서드가 사용
  • 내장 프로토타입은 수정이 가능하나 되도록 변경하지 않는다.
    • 명세서에 새로 등록 된 기능을 쓰고 싶지만 자바스크립트 엔진에 구현되어 있지 않은 경우 정도에만 변경한다.
const num = new Number(100);

// num은 Number.prototype을 상속 받았는가?
console.log(num.__proto__ === Number.prototype);

// num은 Object.prototype을 상속 받았는가?
console.log(num.__proto__.__proto__ === Object.prototype);

// 체인 맨 위에는 null이 있다.
console.log(num.__proto__.__proto__.__proto__);

console.log(num);
// Number에도 toString()이 정의되어 있고, Object에도 toString()이 정의 되어 있다
// 중복 메서드가 있는 경우 체인에서 가까운 메서드가 사용된다.
// Number.prototype의 toString이 사용된다.
console.log(num.toString());

// 내장 프로토타입 수정 가능하나 되도록 변경하지 않는다. 
// 명세서에 새로 등록 된 기능을 쓰고 싶지만 자바스크립트 엔진에 구현되어 있지 않은 경우 정도에만 변경한다.
String.prototype.hello = function(){
    console.log(`hello, ${this}`);
};

"JavaScript".hello();

7-4. Modern Method

1) modern method

  • 프로토타입 접근 시 사용하는 모던 메소드
  • Object.create(proto) : [[Prototype]]이 proto를 참조하는 빈 객체를 만듦
const user = {
    activate : true
};

const student = Object.create(user);
console.log(student.activate);
  • Object.getPropertyOf(obj) : obj의 [[Prototype]]을 반환
console.log(Object.getPrototypeOf(student));
console.log(Object.getPrototypeOf(student) === user);
  • Object.setPrototypeOf(obj, proto) - obj의 [[Prototype]]을 proto가 되도록 설정
Object.setPrototypeOf(student, {});
console.log(Object.getPrototypeOf(student));
  • proto 를 getter, setter로 직접 사용하면 키가 "proto"일 때 에러가 발생하는 의도하지 않은 상황이 발생 할 수 있다.
const obj = Object.create(user);
let key = "__proto__";
console.log(obj[key]);		//obj.__proto__
obj[key] = {test : "새로운 객체 덮어쓰기"};
console.log(obj[key]);
console.log(obj.__proto__);
profile
DREAM STARTER

0개의 댓글