2022. 1. 21. 19:11ㆍ책/자바스크립트 딥다이브
9. 프로토타입 교체
프로토타입은 임의의 다른 객체로 변경할 수 있는데,
이를 활용하면 객체 간 상속관계를 동적으로 변경 가능함
(사실 이 방법은 추천하지 않으며 꽤나 번거로움 걍 "쓰지마")
교체방법 : 생성자 함수 / 인스턴스에 의한 교체
9.1 생성자 함수에 의한 프로토타입 교체
const Person = ( function ( ) }
function Person( name ) { this.name = name }
// 생성자 함수의 프로토타입 프로퍼티를 통해 프로토타입 교체중
Person.prototype = {
// constrouctor : Person, <-- 나 지금 생성자함수 연결 안해놨다!!!! 주석처리함!!
sayHello( ) { console.log('ㅎㅇ') };
}
return Person
} ( ) );
const 샘플인스턴스 = Person( '샘플' );
이렇게 만들면 Person 생성자함수랑 샘플프로토랑 연결자체는 된 상태.
즉, Person 생성자 함수의 프로토타입이 샘플프로토를 가리키고는 있음
다만 constructor로 Person 생성자함수를 가리키게 만들진 않았어서
샘플인스턴스의 생성자 함수를 검색하면 Person이 아니라 Object가 나옴
9.2 인스턴스에 의한 프로토타입 교체
function Person(name) {
this.name = name;
}
const 샘플인스턴스 = Person( '샘플' );
const 샘플프로토 = {
// constructor : Person, <-- 나 지금 생성자함수 연결 안해놨다!!!! 주석처리함!!
sayHello( ) { console.log('ㅎㅇ') };
}
Object.setPrototypeOf( 샘플인스턴스, 샘플프로토 );
이렇게 만들면 Person 생성자함수랑 샘플프로토랑 연결 자체가 안됨.
즉, Person 생성자 함수의 프로토타입이 샘플프로토를 가리키지 않게됨
추가로 constructor로 Person 생성자함수랑 연결 안해놓다보니
샘플인스턴스의 생성자 함수를 검색하면 Person이 아니라 Object가 나옴
꼬우면 constructor : Person 써줘서 연결시켜야댐
10. instanceof 연산자
' 객체 instanceof 생성자함수 ' 방식으로 돌리는데
우변 생성자함수의 프로토타입에 바인딩된 객체가
좌변 객체의 프로토타입 체인 상에 존재하면 true 아니면 false로 평가됨
다시한번 말하지만
프로토타입의 constructor 프로퍼티가 가리키는 생성자 함수를 찾는게 아니라
생성자 함수의 prototype에 바인딩된 객체가 프로토타입 체인 상에 존재하는지를 확인함
둘은 엄연히 다른 말임
const parent = { };
Object.setPrototypeOf(인스턴스, parent);
생성자함수.prototype = parent;
이렇게 만들어뒀을때
parent에 constructor로 생성자함수랑 연결 안시켜놨음에도
instanceof 로 돌려보면 true 로 찍혀나옴
11. 직접 상속
11.1 Object.create 직접 상속
명시적으로 프로토타입을 지정해 새로운 객체를 생성. (OrdinaryObjectCreate 호출)
ㅇ함수
Object.create( prototype [ , propertiesObject ] )
매개변수1 : 프로토타입으로 지정할 객체
매개변수2 : 프로퍼티 키와 프로퍼티 디스크립터 객체로 이뤄진 객체 (생략가능)
ㅇ예시
obj = Object.create( Object.prototype, { x : { value : 1, writable : true, enumerable : true, configurable : true } );
const myProto = { x : 10 }; // 객체 리터럴로 생성한 객체
obj = Object.create( myProto ); // 객체 리터럴로 생성한 객체 상속받기
ㅇ장단점
- new 연산자 없이 객체 생성 가능
- 프로토타입 지정과 동시에 객체 생성 가능
- 객체 리터럴로 생성된 객체도 상속받기 가능
- 대신 두번째 인자로 프로퍼티 정의가 번거롭긴 함
11.2 객체 리터럴 내부에서 __proto__ 로 직접 상속
ㅇ예시
const myProto = { x : 10 };
const obj = {
y: 20,
__proto__ : myProto
};
12. 정적 프로퍼티/메서드
생성자 함수로 인스턴스를 생성하지 않아도 참조/호출할 수 있는 프로퍼티/메서드를 말함
이게 무슨밀이냐..
그냥 함수 자체가 가지고 있는 프로퍼티/메서드를 뜻함.
그리고 얘들은 함수의 프로토타입에 딸려들어가는 애들이 아님
이건 또 무슨말이냐면
인스턴스에서 프로퍼티/메서드를 호출하면
프로토타입을 뒤져가며 프로토타입에 딸린 프로퍼티/메서드를 찾는데
생성자 함수에만 있고 프로토타입엔 안달려있으니 호출이 불가능하단 소리임
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function( ) { console.log('안녕') };
Person.staticProp = '스태틱 프로퍼티요';
Person.staticMethod = function( ) { console.log( '스태틱 메서드요' ) };
const 인스턴스 = new Person( '임시' );
Person.staticMethod( ) // '스태틱 메서드요'
인스턴스.staticMethod( ) // TypeError : 인스턴스.staticMethod is not a function
13. 프로퍼티 존재 확인 (true/false)
13.1 in 연산자
- key in object 방식으로 확인
- 상속받은 모든 프로토타입의 프로퍼티까지 싹다 뒤지니 조심해서 쓰셈
13.2 Object.prototype.hasOwnProperty 메서드
- 객체.hasOwnProperty( '키 뭐 아무거나' )
- 객체 고유의 프로퍼티 키만 확인
14. 프로퍼티 열거
14.1 for ... in
- 객체의 프로토타입 체인 상에 존재하는 모든 프로토타입의 프로퍼티중에서
프로퍼티 어트리뷰터 [[Enumerable]]의 값이 true인 프로퍼티를 순회하며 열거(enumeration)
- 이게 무슨말이냐.. const 샘플객체 = { x : 10 }; 이렇게 만들고
for ( let key in 샘플객체 ) {
console.log( key );
}
하면 x 가 출력되기야 되겠지만
Object.prototype.toString 같은 프로토타입 메서드도 검색 대상에 포함될뻔 한거임
다만 toString의 [[Enumerable]] 값이 false라 순회대상에서 제외되었을뿐..
- const 샘플객체2 = { y : 10, __proto__ : { age : 20 } };
이렇게 만들고 for ... in으로 순회하면 age 까지 같이 출력된다는 얘기임
이게 싫으면 샘플객체.hasOwnProperty( key )로 고유 프로퍼티인지 체크하고 출력되게 하셈
- 참고사항1 심벌로 만든 키는 열거X
- 참고사항2 for ... in 문은 순서 상관없이 열거함(요샌 브라우저 엔진이 재정렬해주긴 하지만ㅋ)
14.2 Object.keys/values/entries 메서드
- 프로토타입까지 싹 다 뒤지는게 싫으면 쓰게 될 메서드
- 순서대로 각각 [ 키 ] / [ 값 ] / [ [ 키 ], [ 값 ] ] 어레이를 반환
'책 > 자바스크립트 딥다이브' 카테고리의 다른 글
[38장] 브라우저의 렌더링 과정 (0) | 2022.01.22 |
---|---|
[20장] strict mode (ES5) (0) | 2022.01.22 |
[19강] 프로토타입(1) (0) | 2022.01.16 |
[16장] 프로퍼티 어트리뷰트 (0) | 2022.01.02 |
[15장] 블록 레벨 스코프 (let, const / var) (0) | 2022.01.01 |