javascript 프로토타입 어렵지 않아요~ 이해하기(prototype,__proto__,prototype chain)

javascript
블로그 이미지

이챙(leechaeng)

﹒2021. 2. 21.

안녕하세요 이번에는 프로토타입에 대해서 포스팅하겠습니다 gogo!

프로토타입(Prototype)은 무엇이냐


			
function Person(){
	this.name = 'rim';
	this.job = 'siger'
}
var obj1 = new Person();
obj1.age = 12;
var obj2 = new Person();

Person 생성자 함수를 만들고 new 키워드를 사용하여 obj1 , obj2 두 인스턴스를 생성하였습니다.
그리고 obj1 인스턴스를 생성한후 age 라는 속성을 만들어주었어요
그럼 obj2에서도 age라는 속성을 사용할 수 있을까요?

정답은 no 입니다!


				
function Person(){
	this.name = 'rim';
	this.job = 'siger'
}

var obj1 = new Person();
obj1.age = 12;
var obj2 = new Person();

console.log(obj1.age); //12
console.log(obj2.age); //undefined
			



obj1 에만 age 속성을 주었기 때문에 obj2 에는 undefined 결과가 나오죠
obj1 , obj2 두객체가 age속성을 공유하려면 필요한것이 바로 prototype 입니다.




				
function Person(){
	this.name = 'rim';
	this.job = 'siger'
}

Person.prototype.age = 12

var obj1 = new Person();
var obj2 = new Person();

console.log(obj1.age); //12
console.log(obj2.age); //12
			

프로토타입은 모든 함수,객체와 연결된 객체입니다.
그렇기 때문에 생성자함수인 Person prototype에 접근하여 age 속성을 넣어주면
obj1 , obj2 가 바라보고 있는것이 Person이기 때문에 age 속성을 공유할 수 있죠
위의코드에서 결과 값이 12가 나오는 걸 확인하실 수 있습니다

위의 그림을 보면 알 수 있듯이
생성자함수를 만들어 새 인스턴스를 만들면 새 객체가 생성되면서
생성자함수의 프로토타입과 서로 공유할 수 있게 되는것이죠!

__proto__

프로토타입은 객체에도 연결되어 있습니다.
그런데 prototype 으로 접근하는 것이 아니라 __proto__ 속성으로 접근가능해요.
변수에 new 키워드로 생성자 함수를 호출하면 새 객체가 만들어지면서 __proto__가 같이 생성됩니다.


				
console.log(typeof Person.prototype) // object
console.log(typeof obj1.prototype) // undefined
console.log(typeof obj1.__proto__) //object

console.log(Person.prototype ===  obj1.__proto__) // true
			

obj1 객체에 prototype으로 접근을 시도하니 undefined결과가 나오죠.
__proto__로 접근하였더니 객체를 반환합니다.

함수의 prototype과 객체의 __proto__가 서로 공유하는 관계이기 때문에
이 둘은 결국 같은거겠죠!
서로 같은지 비교해보면 true를 반환합니다.

그런데 __proto__는 현재 비표준화 되어있어요.
그래서 표준화된 object.getPrototypeOf() 을 사용합니다. 객체의 프로토타입을 반환해주는 메소드에요


				
var obj1Proto = Object.getPrototypeOf(obj1);

proto.firstName = 'lee';

console.log(Person.firstName) // lee
			

새 변수에 object.getPrototypeOf()를 사용하여 obj1를 담아주고 firstName 속성을 추가해주었습니다.
그럼 생성자함수 Person에서도 firstName 속성을 사용할 수 있겠죠
Object.getPrototypeOf(obj1.__proto__)가 들어있다고 생각하시면 됩니다.

Prototype Chain

객체의 __proto__와 함수의 prototype은 서로 공유하는 관계라고 했죠.
바로 서로 연결되어 있다는 뜻입니다. 이걸 prototype chain이라고 합니다 객체가 [[prototype]] 링크를 통해 프로토타입 객체의 메소드와 속성을 사용할 수 있습니다.


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

Person.prototype.desc = function(){
	return this.name + ' 은' + this.job + ' 이다.'
}

var obj1 = new Person('rim','siger');
var obj2 = new Person('young');

obj1.start = function(){
	return this.desc()
}
obj1.start() // "rim 은siger 이다."
obj2.start() // Uncaught TypeError: obj2.start is not a function
			

위의 코드를 그림으로 풀어놓았는데요.
우선 Person함수의 프로토타입에 desc() 메소드를 넣어놨습니다.
obj1과 obj2는 new 키워드를 사용해 person함수를 호출하고 있으니 각각 name,job 속성을 갖게되죠.
그리고 obj1에 start() 메서드를 만들어주었어요.
obj1.start()를 호출하면 함수 안에서 return 값인 desc()를 찾습니다.
근데 obj1안에는 없죠?
이때 프로토타입체인을 타고 Person()의 프로토타입 객체에서 찾습니다.
Person()의 프로토타입에 desc()가 있으니 obj1은 '엇 desc() 메소드가 있네' 하고
이 메소드를 return 해줍니다.
obj2를 봐볼까요?
obj1이랑 obj2가 같은 생성자 함수를 호출하니까 start()메소드를 같이 사용할 수 있을거 같죠?
하지만 아닙니다.
obj1,obj2는 각각 다른 그릇에 생성자함수를 담고있는 것이고
obj1 그릇에만 start메소드를 담아주었으니 obj2에서는 이 함수의 존재도 모르는것이죠.

 

				
obj1.toString() // "[object Object]"
			

 

자 그럼 obj1에 객체의 toString() 메소드를 불러오면 어떻게될까요?
바로 프로토타입체인을 통해서 Object의 toString()메소드를 불러와 객체문자를 반환하게 됩니다.
자바스크립트에 기본적으로 Object()가 내장되어있는데 모든 함수객체가 프로토타입을 가지고 있으니
Object도 프로토타입이 당연히 있겠죠
그래서 Object 속성을 사용할 수 있는거에요.
프로토타입은 연결되어있어 공유할 수 있다를 항상 염두해둡시다

정리

  • 모든 함수는 prototype 객체를 포함하고 있다.
  • new 키워드로 생성자 함수를 호출하면 __proto__가 생성되고 prototype과 공유된다
  • Object.getPrototypeOf() 은 프로토타입 연결에 접근 할 수 있다
  • 객체들이 프로토타입체인을 통해 모든 속성과 메소드를 공유할 수 있다
  • Object()도 프로토타입을 가지고 있다
이챙(leechaeng)
이챙(leechaeng)

프론트엔드 개발도 하고 뛰기도 하고

'javascript' 카테고리의 관련 글