[Javascript] Deep Dive 19장 프로토타입 -2

Yuzu·2023년 7월 27일
0

19.8 오버라이딩과 프로퍼티 섀도잉

const Person = (function () {
	// 생성자 함수
    function Person(name) {
    this.name = name;
    } 
    
    // 프로토타입 메서드
Person.prototype.sayHello= function () {
	console.log(`Hi! My name is ${this.name}`);
    }
    
    // 생성자 함수를 반환
 	return Person;
}());

const me = new Person('Lee');

// 인스턴스 메서드
me.sayHello = function () {
	console.log(`Hey! My name is ${this.name}`);
};

// 인스턴스 메서드 호출, 인스턴스 메서드가 프로토타입 메서드를 가림
me.sayHello(); // Hey! My name is Lee
  • 프로토타입 프로퍼티와 같은 이름의 인스턴스 프로퍼티를 추가하면 인스컨스 메서드는 프로토타입 메서드를 오버라이딩하고 프로토타입 메서드는 가려진다.
    프로퍼티 섀도잉(property shadowing) : 상속 관계에 의해 프로퍼티가 가려지는 현상
    오버라이딩(overriding) : 상위 클래스가 가지고 있는 메서드를 하위 클래스가 재정의하여 사용하는 방식
    오버로딩(overloading) : 함수의 이름은 동일하지만 매개변수의 타입 또는 개수가 다른 메서드를 구현하고 매개변수에 의해 메서드를 구별하여 호출하는 방식
delete me.sayHello; // 인스턴스 메서드 삭제
me.sayHello(); // Hi! My name is Lee ; 프로토타입 메서드 호출
  • 프로퍼티 삭제도 마찬가지로 인스턴스 메서드가 삭제된다.
  • 하위 객체를 통해 프로토타입의 프로퍼티를 변경, 삭제하는 것은 불가능하고 프로토타입에 직접 접근해야한다. == get 액세스는 허용되나 set 액세스는 허용되지 않는다.
// 프로토타입 메서드 변경
Person.prototype.sayHello = function () {
	console.log(`Hey! My name is ${this.name}`);
    };
me.sayHello(); // Hey! My name is Lee

// 프로토타입 메서드 삭제
delete Person.prototype.sayHello;
me.sayHello(); // TypeError, 삭제됨

19.9 프로토타입의 교체

프로토타입은 생성자 함수 또는 인스턴스에 의해 다른 객체로 변경할 수 있다.
== 객체 간의 상속 관계를 동적으로 변경할 수 있다.

1. 생성자 함수에 의한 프로토타입의 교체

2. 인스턴스에 의한 프로토타입의 교체


19.10 instanceof 연산자

이항 연산자로서 좌변에 객체를 가리키는 식별자, 우변에 생성자 함수를 가리키는 식별자를 피연산자로 받는다.

객체 instanceof 생성자 함수

  • 우변의 생성자 함수의 prototype에 바인딩된 객체가 좌변의 객체의 프로토타입 체인 상에 존재하면 true로 평가되고, 그렇지 않은 경우에는 false로 평가된다.
// 생성자 함수
function Person(name) {
	this.name = name;
    }
    
const me = new Person('Lee');

console.log(me instanceof Person); // true, Person.prototpye이 me 객체의 프로토타입 체인 상에 존재
console.log(me instanceof Object); // true, Object.prototpye이 me 객체의 프로토타입 체인 상에 존재
--------------------------
// 프로토타입으로 교체할 객체
const parent = {};
// 프로토타입 교체
Object.setPrototypeOf(me, parent);

// Person 생성자 함수와 parent 객체는 연결되어 있지 않다.
Person.prototype === parent // false
parent.constructor === Person // false

console.log(me instanceof Person); // false
console.log(me instanceof Object); // false 
--------------------------
// parent 객체를 Person 생성자 함수의 prototype 프로퍼티에 바인딩한다.
Person.prototype = parent;

console.log(me instanceof Person); // true
console.log(me instanceof Object); // true 
  • instanceof 연산자는 생성자 함수의 prototype에 바인딩된 객체가 프로토타입 체인 상에 존재하는지 확인한다. constructor 프로퍼티가 가리키는 생성자 함수를 찾는 것이 아님.

19.11 직접 상속

1. Object.create 에 의한 직접 상속

: 명시적으로 프로토타입을 지정하여 새로운 객체를 생성한다.

Object.create(생성할 객체의 프로토타입으로 지정할 객체, 생성할 객체의 프로퍼티 키와 프로퍼티 디스크립터 객체로 이뤄진 객체)

2. 객체 리터럴 내부에서 proto 에 의한 직접 상속


19.12 정적 프로퍼티/ 메서드

: 생성자 함수로 인스턴스를 생성하지 않아도 참조/ 호출할 수 있는 프로퍼티/ 메서드


19.13 프로퍼티 존재 확인

1. in 연산자

: 객체 내에 특정 프로퍼티가 존재하는지 여부를 확인한다.

key : 프로퍼티 키를 나타내는 문자열
object: 객체로 평가되는 표현식
=> key in object

2. Object.prototype.hasOwnProperty 메서드

: 인수로 전달받은 프로퍼티 키가 객체 고유의 프로퍼티 키인 경우에만 true를 반환하고 상속받은 프로토타입의 프로퍼티 키인 경우 false를 반환한다.


19.14 프로퍼티 열거

1. for ... in 문

for ( 변수선언문 in 객체) { ... }

  • 객체의 모든 프로퍼티를 순회하며 열거(enumeration)한다.

  • 순회 대상 객체의 프로퍼티뿐만 아니라 상속받은 프로토타입의 프로퍼티까지 열거한다. 하지만 toString과 같은 Object.prototype의 프로퍼티가 열거되지 않는다. Object.prototype.string 프로퍼티의 프로퍼티 어트리뷰트 [[Enumerable]]의 값이 false이기 때문이다.
  • for... in 문은 객체의 프로토타입 체인 상에 존재하는 모든 프로토타입의 프로퍼티 중에서 [[Enumerable]]의 값이 true인 프로퍼티를 순회하며 열거한다.
  • 배열에는 일반적인 for문이나 for... of 문 또는 forEach 메서드를 사용 권장한다.

2. Object.keys/values/entries 메서드

: 상속받은 프로퍼티를 제외한 객체 자신의 고유 프로퍼티만 열거하는 메서드

  • Object.keys(객체) : 객체 자신의 열거 가능한 프로퍼티 키를 배열로 반환
  • Object.values(객체) : 객체 자신의 열거 가능한 프로퍼티 값을 배열로 반환
  • Object.entries(객체) : 객체 자신의 열거 가능한 프로퍼티 키와 값의 쌍의 배열을 배열에 담아 반환
profile
냐하

1개의 댓글

comment-user-thumbnail
2023년 7월 27일

잘 봤습니다. 좋은 글 감사합니다.

답글 달기