JS prototype (PurpleCode Study)

김지원·2020년 11월 3일
0

JavaScript

목록 보기
6/21

[[Prototype]]

  • 자바스크립트의 객체는 명세서에서 명명한 [[Prototype]]이라는 숨김 프로퍼티를 갖는다.
  • 숨김 프로퍼티 값은 null 또는 다른 객체에 대한 참조
  • 다른 객체를 참조하는 경우 참조 대상을 프로토타입(prototype)이라고 한다.

프로토타입의 동작 방식

  • object에서 프로퍼티를 읽으려고 하는데 해당 프로퍼티가 없다면 자바스크립트는 자동으로 프로토타입에서 프로퍼티를 찾는다.
  • 이런 동작 방식을 프로토타입 상속이라고 부른다.

[Prototype] 프로퍼티는 내부 프로퍼티이면서 숨김 프로퍼티이지만 개발자가 값을 설정할 수 있다.

__proto__를 사용하면 값을 설정할 수 있다.

let car = {
	numberOfWheels:4
   };
   
let hyundaiCar ={
	brand: "hyundai"
   };
   
hyundaiCar.__proto__=car;

console.log(car.numberOfWheels);//4
console.log(hyundaiCar.brand);//hyundai
console.log(hyundaiCar.numberOfWheels);//4
  • 여기서 __proto__[[prototype]]getter, setter이다.
  • 근래에는 __proto__대신 Object.getPrototypeOf, Object.setPrototypeOf를 써서 프로토타입을 획득하거나 설정한다.

객체 hyundaiCar에서 프러퍼티를 얻고 싶은데 해당 프로퍼티가 없다면 자동으로 car 객체에서 프로퍼티를 얻는다.
hyundaiCar의 프로토타입은 car이다.
혹은 "hyundaiCarcar를 상속받는다."라고 할수있다.
numberOfWheels 같은 프로퍼티를 상속받은 프로퍼티로 상속 프로퍼티라고 부른다.

상속 메서드

let car = {
    numberOfWheels:4,
    drive(){
        console.log("drive 가능!");
    }
   };
   
let hyundaiCar ={
    brand: "hyundai",
    __proto__:car
   };

(hyundaiCar.drive();//drive 가능!

프로토타입은 프로퍼티를 읽을때만 사용한다.

프로퍼티를 추가, 수정, 삭제 연산은 객체에 직접해야한다.

let car = {
    numberOfWheels:4,
    drive(){
        console.log("drive 가능!");
    }
   };
   
let hyundaiCar ={
    brand: "hyundai",
    __proto__:car
   };

hyundaiCar.drive=function(){
  console.log("현대차 운전 가능!");
}

hyundaiCar.drive();//현대차 운전 가능!

프로토타입에 있는 메서드가 실행되지 않고, 객체 hyundaiCar에 추가한 메서드가 실행됨

접근자 프로퍼티

let car = {
    numberOfWheels:4,
    set wheels(value){
        this.numberOfWheels= value;
    },
    get wheels(){
        return this.numberOfWheels;
    }
   };
   
let bus ={
    __proto__:car
   };

//getter 함수 호출
console.log(bus.wheels);//4

//setter 함수 호출
bus.wheels=6
console.log(bus.wheels);//6

"this"가 나타내는 것

set wheels(value){ this.numberOfWheels= value; }this에는 어떤 값이 들어갈까?
car에 저장될까 bus에 저장될까?

A) this는 프로토타입에 영향을 받지 않는다.
메서드를 객체에서 호출했든 프로토타입에서 호출했든 상관없이 this는 언제나 . 앞에 있는 객체가 된다!

let car = {
    numberOfWheels:4,
   drive(){
       if(!this.isBreak){
           console.log("drive 모드");
       }
   },
   break(){
       this.isBreak = true;
    }
   };
   
let bus ={
    __proto__:car
   };

let taxi ={
    __proto__:car
}

bus.break();
console.log(bus.isBreak);//true

console.log(taxi.isBreak);//undefined
console.log(car.isBreak);//undefined

bus.numberOfWheels=6;
console.log(car.numberOfWheels);//4
console.log(bus.numberOfWheels);//6
console.log(taxi.numberOfWheels);//4

함수의 prototype 프로퍼티와 constructor 프로퍼티

  • 개발자가 특별히 할당하지 않더라도 모든 함수는 prototype 프로퍼티를 갖고있다.
  • 기본 프로퍼티인 prototypeconstructor 프로퍼티 하나만 있는 객체를 가리키는데, 이 constructor 프로퍼티는 함수 자신을 가리킨다.
function food() {}

console.log(food.prototype);
//food {}
console.log(food.prototype.constructor);
//[Function: food]

constructor 프로퍼티 사용해보기

constructor를 이용해서 새로운 객체를 만들 수 있다.

function Food(name, star) {
    this.name=name;
    this.star=star;
    console.log(`${name}의 별점은 ${star}점 !!`);
}

let cake = new Food("케이크", 4);//케이크의 별점은 4점 !!
let coffee = new cake.constructor("커피", 3);//커피의 별점은 3점 !!

console.log(cake);//Food { name: '케이크', star: 4 }
console.log(coffee);//Food { name: '커피', star: 3 }

proto를 사용하지 않는 이유

proto를 써서 프로토타입을 그때그때 바꾸는 연산은 객체 프로퍼티 접근 관련 최적화를 망치기 때문에 매우 느리다!

권장 메소드

  • Object.create(proto, [descriptors]) : proto를 참조하는 빈 객체를 만든다. 여기서 프로퍼티 설명자를 추가로 넘길 수 있다.
  • Object.getPrototypeOf(obj) : obj의 [[Prototype]]을 반환한다.
  • Object.setPrototypeOf(obj,proto) : obj의 [[Prototype]]이 proto가 되도록 설정한다.

0개의 댓글