딥다이브 스터디 19(프로토타입)

김영현·2023년 10월 9일
0

서론

대망의 프로토타입. 사실 이전에 OOJS를 다루며 설명해놓은 글이 있긴하다.
더 간략히 요약해보는 시간을 가져보자.


JS는 사실 객체지향

클래스 기반 객체지향이 아닌 프로토타입 기반 객체지향
=> 원시타입을 제외한 모든 것이 객체.

객체지향 프로그래밍(OOP)

명령,함수 목록으로 보는 절자치향에서 벗어나 여러개의 독립적 단위(객체)의 집합으로...
=> 쉽게 말해 클래스에서 기능을 다 묶고 객체를 생성(인스턴스화) 하면, 사용할땐 현실처럼 내부 동작을 몰라도 사용할 수 있다.

내부 데이터(상태)는 프로퍼티, 객체의 내부 데이터를 조작하는 함수(동작)을 메소드라고 함.

객체는 독립적일 수도있고, 다른 객체와 관계를 맺을수도, 다른 객체의 상태나 동작을 상속받아 사용할수도 있다.
=> 재사용성이 용이하고, 의존성 주입이 쉽다.

오버라이딩, 섀도잉

객체지향에서 자주쓰는 말이다. 살짝 헷갈린다.

  • 오버라이딩 : 상속받아온 프로퍼티를 재정의해서 사용함.
  • 섀도잉 : 오버라이딩해서 상위 프로퍼티가 숨겨짐.

그렇다.


상속, 프로토타입

클래스 기반 객체지향에선 상속을 통해 부모 클래스의 프로퍼티와 메소드를 받아옴.
이를 JS에선 프로토타입으로 구현함.
둘 다 불필요한 중복을 제거.
But, 프로토타입자식클래스가 직접 상속받는 것이 아님. 프로토타입이 갖고있는걸 나눠쓴다.
따라서 클래스 기반 객체지향보다 메모리 낭비를 덜함.

프로토타입 객체

프로토타입 객체지향이라는 뜻은, 우리가 사용하는 객체타입도 결국프로토타입이 존재함을 뜻함.
=> [[Prototype]] 내부 슬롯.


__proto__접근자로 접근 가능.
ES6이후에는 get, setPrototypeOf()를 사용
참고로 이렇게 프로토타입을 수정하는건 권장되지 않음.
Object.create()로 새로운 참조를 생성해야한다.
=> 프로토타입체이닝을 모두 바꿔야하기때문

접근자는 곧 get,set을 사용한다는 뜻.
read-write가 가능하게 만든 이유는 내부적으로 상호참조를 방지하기 위해서.
a,b가 서로를 프로토타입으로 참조하면 순환참조 에러.

나머지 사항은 이렇다.

  • 생성자 함수객체prototype은 생성될 인스턴스의 프로토타입
  • 모든 프로토타입은 constructor프로퍼티를 가짐. 생성자함수를 가리킴.
  • 리터럴표기법으로 생성한 객체{}는 생성자함수로 생성된 건 아니지만, constructor가 제대로 들어가있다.

객체 생성방식-프로토타입 결정

  • 객체 리터럴{} : Object.prototype
  • Object 생성자 함수Object() : Object.prototype
  • 생성자함수function(){this...}: 생성자함수 prototype에 바인딩 되어있는 객체

프로토타입 체인

스코프체인처럼 프로토타입도 계속해서 프로토타입 참조를 타고(상위) 호출한 프로퍼티를검색한다.
=> 상위의 모든 프로토타입은 전부 상속받았다고 보면 된다.

최상위 프로토타입 객체Object.prototype이다.
따라서 모든 객체가 이를 상속받는다.
=> 그 위는 null이다

프로토타입 변경


본래는 생성자함수의 constructorPerson이 프로토타입이어야함.
__proto__로 변경할수도있다.
둘다 권장x

instance of 연산자

객체 instanceof 생성자함수 이렇게 사용함.
=> 이 인스턴스가 생성자함수로 만든것이냐~
생성자함수의 prototype에 바인딩된 객체가 프로토타입 체인상에 존재하면 true다.

직접 상속

아까 설명했던 Object.create()은 명시적으로 프로토타입을 선언하여 새로운 객체를 생성한다.

Object.create(프로토타입);
  • new연산자가 없이도 객체생성 가능
  • 프로토타입 지정하면서 객체 생성 가능
  • 객체 리터럴에 의해 생성된 객체도 상속가능

장점이 많다.
여담으로 ESlint는 빌트인 메소드를 바로 사용하는걸 권장하지 않음
Object.create(null)로 종점 프로토타입을 가진 객체생성이 가능하기때문.
=> 이렇게 생성한 객체로 빌트인 메소드를 호출하면 에러가난다.

정적 메소드

클래스에서 static을 사용하여 선언한 정적 메소드는 사실 이렇게 구현된다.

function Person(name){
	this.name = name;
}
Person.staticMethod = function (){
	return "hi";
}
Person.staticProp = "bye";
const person = new Person("kim");
person.staticprop // ...undefined
person.staticMethod() // is not a function...

인스턴스에서는 참조 불가. 생성자함수에서 참조 가능.

프로퍼티 존재 확인

  • in연산자를 사용하여 확인한다.
    즉, for...in메소드는 객체를 순회하며 [[Enumrable]]한 프로퍼티를 열거함.(상속받은 프로퍼티도 가능).
  • Object.keys, values, entries()는 고유한 객체 프로퍼티만 열거.
  • hasOwnProperty는 상속받지 않은 고유한 객체의 프로퍼티인지 확인

참고로 모던 브라우저는 숫자인 프로퍼티 키에 대해서 정렬함!

profile
모르는 것을 모른다고 하기

0개의 댓글