[js] 프로토타입

프로토타입

프로토타입

Contructor   prototype 
    | new    / 
    |       /
    |      /
instance  __proto__

prototype property는 아래와 같은 특성을 가진다.

따라서, Object.key

모든 함수는 prototype이라는 특수한 프로퍼티를 가진다.

프로토타입 가져오기.

// example1
const person = {
	name: 'mike',
}
const prototype = Object.getPrototypeOf(person);
console.log(typeof prototype);
console.log(person.___proto__ === prototype);

// example2
const Person = function () {
    
};
const pius = new Person();
Object.getPrototypeOf(pius);
// >>> Pius
Object.getPrototypeOf(pius) === pius.__proto__
// >>> true

프로토타입 설정하기

new Operation을 사용하면, 생성자 함수의 prototype property를 인스턴스의 __proto__ 가 가리킨다.

// new operation
const Person = function () {
    
};
const pius = new Person();
pius.__proto__ === Person.prototype
>>> true

// manually 
const Person = function () {
    
};
const pius = {
    name: 'pius'
};
Object.setPrototypeOf(pius, Person);
pius.__proto__
>>> Person

prototype chain

const person = { 
	name: 'pius',
}
const programmer = {
	language: 'js'
} 
const frontendDev = {
	framework: 'react'
}

Object.setPrototypeOf(programmer, person);
Object.setPrototypeOf(frontendDev, programmer);

// 자신에게 해당 속성이 없으면 프로토타입을 따라서 올라가게 된다.
console.log(frontendDev.name, frontendDev.language);
>> pius js

console.log(
	frontendDev.__proto__.__proto__.name,
	frontendDev.__proto__.language
);
>>> pius js
const person = { 
	name: 'pius',
}
const programmer = {
	language: 'js'
}
Object.setPrototypeOf(programmer, person);
programmer.name = 'pius712'
console.log(programmer.name);
>>> pius712
console.log(person.name);
>>> pius
// 덮어 쓰는 것이 아니라, 자기 자신의 포로퍼티에 할당을 하고, 프로토타입의 속성은 shadowing 된다. 

prototype 상속

const person = { 
	name: 'pius',
}
const programmer = {
	language: 'js'
}
Object.setPrototypeOf(programmer, person);

for (const prop in programmer) {
	console.log(prop);
}
>>> language
>>> name

for (let prop in programmer) {
	if(programmer.hasOwnProperty(prop) {
		console.log(prop);
	}
}
>>> language
for (let prop of Object.keys(programmer)){
	console.log(prop);
}
>>> langugage

생성자 함수

- 모든 함수는 프로토타입 프로퍼티를 가진다. 
- 모든 함수의 프로토타입은 `Function.prototype` 이다.  ```javascript function Person(name) {
// this = {};
this.name = name;
// return this; } const person = new Person('pius'); console.log(person.name); >>> pius console.log(person); >>> { name : 'pius' }; ```
function Person(name) {
	this.name = name;
}
const person = new Person('pius');

console.log(Person.prototype);
// Person.prototype
// 이거는 프로토타입 속성
console.log(Object.getPrototypeOf(person); 
// person.__proto__
// 이것은 프로토타입

person.__proto__ === Person.prototype
>>> true
function Person(name) {
	this.name = name;
}
const citizen = new Person('pius');

console.log(Object.getPrototypeOf(Person) !== Person.prototype);

console.log(Object.getPrototypeOf(citizen) === Person.prototype);

console.log(Object.getPrototypeOf(Person) === Object.prototype);

console.log(Object.getPrototypeOf(Person) === Function.prototype);

console.log(Object.getPrototypeOf(Object) === Function.prototype);

console.log(Object.getPrototypeOf(Function.prototype) === Object.prototype);

console.log(Object.getPrototypeOf(Object.prototype) === null); 

기본 타입 (리터럴 생성)

const obj = {};
const arr = [];
const num = 123.456;
const str = 'abc';

console.log(Object.getPrototypeOf(obj) === Object.prototype); 

console.log(Object.getPrototypeOf(arr) === 
Array.prototype);

console.log(Object.getPrototypeOf(num) === Number.prototype);

console.log(Object.getPrototypeOf(str) === String.prototype);

console.log(num.toFixed === Number.prototype.toFixed);

프로토타입 프로퍼티 수정

function Person(name) {
	this.name = name;
}

const person1 = new Person('mike');

const newPrototype = {
	arr : [],
	push(value) {
		this.arr.push(value);
	},
	getArr(){ 
		return this.arr
	}
}

Person.prototype = newPrototype;
const person2 = new Person('pius');
console.log(Object.getPrototypeOf(person1) 
					!== newPrototype);
>>> true
console.log(Object.getPrototypeOf(person2) 
					=== newPrototype);
>>> true
person2.push(1);
person2.push(2);
console.log(person2.getArr());

상속 최적화

function Person() {
	this.fn1 = function () {},
	this.fn2 = function () {},
}
const person1 = new Person();
const person2 = new Person();
>> 인스턴스 생성마다 fn1, fn2 함수가 생성된다.

function Person() { }
Person.prototype = {
	fn1 = function () {},
	fn2 = function () {}
}
const person1 = new Person();
const person2 = new Person();
>> 프로토타입에 있는 함수의 경우, 객체마다 복사하지 않고 참조하기 때문에 함수를 복사하지 않아서 메모리 효율적이다. 

Constructor

function Person(name) {
	this.name = name;
}
console.log(Person.prototype.constructor === Person);
>>> true
console.log(Person.constructor === ?);
// Person에는 constructor라는 프로퍼티가 없다. 
// 따라서 Person.__proto__.constructor를 찾아간다.
// Person.__proto__.constructor === Person.constructor
// Person.__proto__ 는 Function 객체의 prototype 프로퍼티이다. 
// Function 객체의 prototype 프로퍼티에 해당하는 객체는
// Function 객체를 가리키는 constructor 프로퍼티가 있는데,
// Person.constructor는 이를 가리키는 것.

프로토타입 상속

function Person(name, age) {
	this.name = n;
	this.age = a;
}

Person.prototype.setOlder = function() {
	this.age += 1;
}
Person.prototype.getAge = function() {
	return this.age;
}

var person1 = new Person('pius1', 29);
var person2 = new Person('pius2', 30);

person1.setOlder();
person1.getAge();
person2.setOlder();
person2.getAge();

#javascript/객체#