me의 프로토타입은 프로토타입은 Person.prototype 이다.
//person 생성자 함수
function Person(name) {
this.name = name;
}
// 프로토타입 메서드
Person.prototype.sayHello = function () {
cosnole.log("Hi! My name is ${this.name}");
}
//person 함수에 의해 생성된 me
const me = new Person('Lee');
//me객체는 Object.prototype의 메서드인 hasOwnProperty 호출가능
console.log(me.hasOwnProperty('name')); // true
//Person.prototype의 프로토타입은 Object.prototype이다.
Object.getPrototypeOf(me) === Person.prototype; // true
Object.getPrototypeOf(Person.prototype) === Object.prototype; // true
me.hasOwnProperty('name');
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
- 오버라이딩이란? 상위 클래스가가지고 있는 메서드를 하위 클래스가 재정의하여 사용하는 방식
- 오버로딩? 함수의 이름은 동일하지만 매개변수의 타입 또는 개수가 다른 메서드를 구현하고
매개변수에 의해 메서드를 구별하여 호출하는 방식이다.
프로퍼티를 삭제하는 경우도 마찬가지이다.
//인스턴스 메서드를 삭제한다.
delete me.sayHello;
//인스턴스에서는 sayHello 메서드가 없으므로 프로토타입 메서드가 호출된다.
me.sayHello(); // Hey! My name is Lee
// 프로토타입 체인을 통해 프로토타입 메서드가 삭제되지 않는다.
delete me.sayHello;
// 프로토타입 메서드가 호출된다.
me.sayHello();// Hi! My name is Lee
// 프로토타입 메서드 변경
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: me.sayHello is not a function
프로토타입은 임의의 다른 객체로 변경가능하다.
부모 객체인 프로토타입을 동적으로 변경할 수 있다는 의미이다.
const Person = (function () {
function Person(name) {
this.name = name;
}
// ① 생성자 함수의 prototype 프로퍼티를 통해 프로토타입을 교체
Person.prototype = {
sayHello() {
console.log(`Hi! My name is ${this.name}`);
}
};
return Person;
}());
const me = new Person('Lee');
// 생성자 함수의 constructor와 연결 끊김
console.log(me.constructor === Person); // false
console.log(me.constructor === Object); // ture
① 에서 Person.prototype에 객체 리터럴을 할당.
이것은 Person 생성자 함수가 생성할 객체의 프로토타입을 객체 리터럴로 교체한 것이다.
프로토타입으로 교체한 객체 리터럴에는 constructor 프로퍼티가 없다.
(constructor 프로퍼티는 자바스크립트 엔진이 프로토타입을 생성할 때 암묵적으로 추가한 프로퍼티이다.
따라서 me객체의 생성자 함수를 검색하면 Person이 아닌 Object가 나온다.
function Person(name) {
this.name = name;
}
const me = new Person('chanmi');
//프로토타입으로 교체할 객체
const parent = {
sayHello() {
console.log(`hi my name is ${this.name}`);
}
};
// 1. me 객체를 프로토타입을 parent객체로 교체
Object.setPrototypeOf(me, parent);
// 2. 1번과 동일하게 동작
me.__proto__ = parent;
me.sayHello(); // hi my name is chanmi
const myProto = { x: 10 };
//객체 리터럴에 의해 객체를 생성하면서 프로토타입을 직접 상속받을 수 있다.
const obj = {
y: 20,
// 직접 상속
// obj -> myProto -> Object.prototype -> null
__proto__: myProto
};
console.log(obj.x, obj.y); // 10 20
console.log(Object.getPrototypeOf(obj) === myProto) // true
in연산자는 객체 내에 특정 프로퍼티가 존재하는지 여부를 확인한다.
key in object
const person = {
name: 'lee',
address: 'seoul'
};
//person 객체에 name프로퍼티가 존재한다.
console.log('name' in person); // true
//person 객체에 address프로퍼티가 존재한다.
console.log('address' in person); // true
console.log('age' in person); // false
// 객체가 상속받은 모든 프로토타입의 프로퍼티를 확인함.
// toString은 Object.prototype의 메서드임.
console.log('toString' in person); // true
in연산자 대신 ES6에 도입된 Reflect.has 메서드 사용
// Reflect.has 메서드 사용
const person = { name: 'lee' };
console.log(Reflect.has(person, 'name')); // true
Object.prototype.hasOwnProperty 메서드
객체의 모든 프로퍼티를 순회하며 열거하려면 for...in문을 사용한다.
사용법: for (변수선언문 in 객체) { ... }