const user = {
activate : true,
login : function () {
console.log('로그인 되었습니다');
}
};
const student = {
passion : true
};
proto 는 [[Prototype]] 의 getter, setter
"student의 프로토타입은 user이다." 또는 "student는 user를 상속 받는다." 라고 표현한다.
프로토타입에서 상속 받은 프로퍼티를 상속 프로퍼티라고 한다.
student.__proto__ = user; //student의 프로토타입을 user로 설정
console.log(student.activate);
student.login();
console.log(student.passion);
const greedyStudent = {
class : 11,
__proto__ : student
};
console.log(greedyStudent.activate); // user에서 상속 받은 상속 프로퍼티
console.log(greedyStudent.passion); // student에서 상속 받은 상속 프로퍼티
//객체 생성
const user = {
id : 'user',
login () {
console.log(`${this.id}님 로그인 되었습니다.`);
}
};
const student = {
// 프로토 타입설정
__proto__ : user
};
프로토타입은 프로퍼티를 읽을 때만 사용하며 프로퍼티 추가, 수정, 삭제 연산은 객체에 직접한다.
// student 객체에 id 프로퍼티 추가
student.id = 'user01';
// login 메소드 내의 this는 프로토타입에 영향 받지 않으며 this는 언제나 . 앞에 있는 객체를 의미한다. (student)
student.login();
//출력: user01님 로그인 되었습니다.
hasOwnProperty(key) : 상속 프로퍼티인지 확인하는 메소드
for(let key in student) {
console.log(key);
// key에 대응하는 프로퍼티가 상속 프로퍼티가 아니라 객체에 직접 구현 된 프로퍼티일 경우 true 반환
let isOwn = student.hasOwnProperty(key);
if(isOwn) {
console.log(`객체 자신의 property : ${key}`);
} else {
console.log(`상속 property : ${key}`);
}
}
new 연산자를 사용해 만든 객체는 생성자 함수의 프로토타입 정보를 사용해 [[Prototype]]을 설정한다.
new연산자를 통해 만든 인스턴스에 프로토타입을 설정할 경우
일일이 선언하지 않고, a유형의 인스턴스를 만들 때는 A를 프로토 타입으로 하도록 설정하는 방법
//객체 생성
const user = {
activate : true,
login () {
console.log('로그인 되었습니다');
}
};
function Student(name) {
this.name = name;
}
설정 방법
.prototype 이라는 프로퍼티에 프로토타입으로 설정할 객체를 담는다.
// 여기서의 prototype은 앞에서 배운 프로토타입(__proto__)과 이름만 같을 뿐 실제로는 일반 프로퍼티이다.
Student.prototype = user;
// Function(Student).prototype은 new F를 호출할 때만 사용이 된다.
// new F를 호출할 때 만들어지는 새로운 객체의 [[Prototype]]을 할당한다.
// student.__proto__ == user
let student = new Student("홍길동");
let student2 = new Student("유관순");
console.log(student.activate);
student2.login();
개발자가 특별히 할당하지 않아도 모든 함수는 기본적으로 "prototype" 프로퍼티를 갖는다.
디폴트 프로퍼티 "prototype"은 constructor 프로퍼티 하나만 있는 객체를 가리키는데, 여기서 consturctor 프로퍼티는 함수 자신을 가리킨다.
// 함수를 만들기만 해도 디폴트 프로퍼티인 prototype이 설정된다.
// Student.prototype = { constructor : Student };
function Student() {}
console.log(Student.prototype.constructor);
console.log(Student.prototype.constructor == Student); //true
// 기본 프로토타입을 상속받는 객체 테스트
let student = new Student(); // { constructor : Student }를 상속 받음
console.log(student.constructor);
console.log(student.constructor == Student); //true
Object는 내장 객체 생성자 함수인데 이 생성자 함수의 prototype은 toString을 비롯 다양한 메소드가 구현 된 거대한 객체를 참조한다.
new Object(), {} 를 사용해 객체를 만들 때 만들어진 객체의 [[Prototype]]은 Object.prototype을 참조한다.
const obj = {};
console.log(obj.__proto__ === Object.prototype);
//true
console.log(obj.toString === obj.__proto__.toString);
//true
console.log(obj.toString === Object.prototype.toString);
//true
Function, String, Number를 비롯한 내장 객체들 역시 프로토타입에 메서드를 저장한다.
모든 내장 프로토타입 상속 트리 꼭대기에는 Object.prototype이 있어야 한다고 규정한다.
const num = new Number(100);
// num은 Number.prototype을 상속 받았는가? true
console.log(num.__proto__ === Number.prototype);
// num은 Object.prototype을 상속 받았는가? true
console.log(num.__proto__.__proto__ === Object.prototype);
// 체인 맨 위에는 null이 있다.
console.log(num.__proto__.__proto__.__proto__);
// Object.prototype에도 toString이 있지만 중복 메서드가 있는 경우 체인에서 가까운 메서드가 사용되어
// Number.prototype의 toString이 사용 된다.
console.log(num); // [Number:100]
console.log(num.toString()); //100
내장 프로토타입 수정 가능하나 되도록 변경하지 않는다.
명세서에 새로 등록 된 기능을 쓰고 싶지만 자바스크립트 엔진에 구현되어 있지 않은 경우 정도에만 변경한다.
// 프로토타입 추가
String.prototype.hello = function () {
console.log(`hello, ${this}`);
};
"JavaScript".hello(); //출력 : hello, JavaScript

string.prototype에 정의되어있는 메소드들이다.
여기서 방금 만든 hello()도 호출할 수 있다.
프로토타입 접근 시 사용하는 모던 메소드
// 객체 생성
const user = {
activate : true
};
const student = Object.create(user);
console.log(student.activate);
Object.getPrototypeOf(obj) - obj의 [[Prototype]]을 반환
getPrototypeOf(student) : 프로토타입이 무엇인지 알 수 있는 메소드
console.log(Object.getPrototypeOf(student));
console.log(Object.getPrototypeOf(student) === user);
setPrototypeOf : 프로토타입을 설정하는 메소드
Object.setPrototypeOf(student, {});
console.log(Object.getPrototypeOf(student));
console.log(Object.getPrototypeOf(student) === user);
const obj = Object.create(user);
let key = "__proto__";
console.log(obj[key]);
//내장된 __proto__ 객체를 덮어쓸 수 있다.
obj[key] = { test : "새로운 객체 덮어쓰기" };
console.log(obj[key]);
console.log(obj.__proto__);