프로토타입(2)
10. 프로토타입의 교체
프로토타입은 다른 임의의 객체로 변경할 수 있다. (부모 객체인 프로토타입을 동적으로 변경할 수 있다는 것을 의미)
이러한 특징을 기반으로 객체 간의 상속 관계를 동적으로 변경할 수 있다.
프로토타입은 생성자 함수 또는 인스턴스에 의해 교체할 수 있다.
10.1 생성자 함수에 의한 프로토타입의 교체
1 | const Person = (function () { |
- @에서 Person.prototype에 객체 리터럴을 할당.교체
- 프로토타입으로 교체한 객체 리터럴에는 constructor 프로퍼티가 없다.
- me 객체의 생성자함수를 검색하면 Person이 아닌 Object가 나온다.
1
2
3
4//프로토타입을 교체하면 constructor 프로퍼티와 생성자 함수 간의 링크가 파괴된다.
console.log(me.constructor === Person); //false
//프로토타입 체인을 따라 Object.prototype의 constructor 프로퍼티가 검색된다.
console.log(me.constructor === Object); //true - 프로토타입으로 교체한 객체 리터럴에 constructor 프로퍼티를 추가하면 프로토타입의 constructor 프로퍼티를 되살릴 수 있다.
10.2 인스턴스에 의한 프로토타입의 교체
인스턴스의 proto 접근자 프로퍼티 (or Object.setPrototypeOf메소드)를통해 타입을 교체할 수 있다.
1 | function Person(name) { |
- 생성자 함수로 프로토타입 교체한 것처럼 프로토타입으로 교체한 객체는 constructor가 없다
- me 객체의 생성자 함수를 검색하면 Person이 아닌 Object가 나온다.
11. instanceof 연산자
- instanceof 연산자는 이항 연산자로서 좌변에 객체를 가리키는 식별자, 우변에 생성자 함수를 가리키는 식별자를 피연산자로 받는다. 우변의 피연산자가 함수가 아닌 경우 TypeError
- 좌변의 객체가 우변의 생성자 함수와 연결된 인스턴스라면 true로 평가되고 그렇지 않은 경우 false로 평가된다.
- instanceof 연산자는 상속관계를 고려한다
1 | function Person(name) { |
- instanceof 연산자는 프로토타입의 constructor 프로퍼티가 가리키는 생성자 함수를 찾는 것이 아니라 프로토타입 체인 상에 존재하는 프로토타입에 영향을 받는다.
…..
12. 직접 상속
12.1 Object.create에 의한 직접 상속
Object.create 메소드는 명시적으로 프로토타입을 지정하여 새로운 객체를 생성한다.
Object.create 메소드도 다른 객체생성방식과 마찬가지로 추상연산 ObjectCreate를 호출한다.
Object.create 첫번째 매개변수에 생성할 객체의 프로토타입으로 지정할 객체를 전달,
두번째 매개변수에는 생성할 객체의 프로퍼티를 갖는 객체를 전달한다.이 객체 형식은 Object.definePropeties 메소드의 두번째 인수와 동일하다.
Object.create 메소드는 첫번째 매개변수에 전달한 객체의 프로토타입 체인에 속하는 객체를 생성한다. 객체를 생성하면서 직접적으로 상속을 구현.
- new 연산자 없이도 객체를 생성할 수 있다.
- 프로토타입을 지정하면서 객체를 생성할 수 있다. 이때 생성자 함수와 프로토타입 간의 링크가 파괴되지 않는다.
- 객체 리터럴에 의해 생성된 객체도 특정 객체를 상속받을 수 있다.
Object.prototype의 빌트인 메소드는 모든 객체의 프로토타입 체인의 종점인 Object.prototype의 메소드이므로 모든 객체가 상속받아 호출할 수 있다.
1 |
|
12.2 객체 리터럴 내부에서 proto에 의한 직접 상속
ES6에서는 객체 리터럴 내부에서 proto 접근자 프로퍼티를 사용하여 직접 상속을 구현할 수 있다.
1 | const myProto = { x: 10 }; |
13. 정적 프로퍼티/메소드
정적(static) 프로퍼티, 메소드는 생성자 함수로 인스턴스를 생성하지 않아도 참조, 호출할 수 있는 프로퍼티, 메소드를 말한다.
14. 프로퍼티 존재 확인
in 연산자는 객체 내에 프로퍼티가 존재하는지 여부를 확인한다.
key : 프로퍼티 키를 나타내는 문자열
object: 객체로 평가되는 표현식
key in object
1 | const person = { |
in 연산자는 확인 대상 객체(person객체)의 프로퍼티 뿐만 아니라 확인 대상 객체가 상속받은 모든 프로토타입의 프로퍼티를 확인하므로 주의.
1 | console.log('toString' in person); //true |
in 연산자가 person 객체가 속한 프로토타입 체인 상에 존재하는 모든 프로토타입에서 toString 프로퍼티를 검색했기 때문이다. toString은 Object.prototype의 메소드
- Object.prototype.hasOwnProperty메소드는 객체 고유의 프로퍼티인 경우에만 true
상속받은 프로토타입의 프로퍼티인 경우 false를 반환
15. 프로퍼티 열거
15.1 for…in 문
객체의 모든 프로퍼티를 순회하며 열거하려면 for…in문을 사용한다.
for (변수선언문 in 객체) {…}
1 | const person = { |
- for…in 문은 객체의 프로퍼티 개수만큼 반복
- in 연산자처럼 순회 대상 객체의 프로퍼티 뿐만 아니라 상속받은 프로토타입의 프로퍼티까지 열거
- 배열에는 for…in문을 사용하지 말고 일반적인 for문이나 for…of문 또는
Array.prototype.forEach메소드를 사용하기를 권장
1 | const arr [1, 2, 3]; |
15.2 Object.keys/values/entries 메소드
- 객체 자신의 프로퍼티만을 열거하기 위해서는 for…in문을 사용하는 것보다
- Object.keys/values/entries 메소드를 사용하는 것을 권장한다.
- Object.keys 메소드는 객체 자신의 열거 가능한 프로퍼티 키를 배열로 반환한다.
1 | const person = { |
ES8에서 도입된 Object.values 메소드는 객체 자신의 열거 가능한 프로퍼티 값을 배열로 반환한다.
1 | console.log(Object.values(person)); //['jung', 'gimpo'] |
ES8에서 도입된 Object.entries 메소드는 객체 자신의 열거 가능한 프로퍼티 키와 값의 쌍의 배열을 배열에 담아 반환한다.
1 | console.log(Object.entries(person)); |