Prototype

midohree·2020년 7월 21일
0
post-thumbnail
post-custom-banner

Prototype ??

자바스크립트는 프로토타입 기반 객체지향 프로그래밍 언어이다. 자바스크립트의 모든 객체는 자신의 부모 역할을 담당하는 객체와 연결되어있다. 그리고 이것은 마치 객체 지향의 상속 개념과 같이 부모 객체의 프로퍼티 또는 메소드를 상속받아 사용 할 수 있게 한다. 이러한 부모 객체를 Prototype(프로토타입) 이라고 한다.

객체는 어떻게 만들어질까? 🤔

const obj = {};
const arr = [];
const func = function () {};

흔히 우리는 위와 같이 객체를 생성한다. 하지만 자바스크립트는 사실상 내부적으로 생성자 함수를 이용해 만드는 것과 동일하게 객체를 생성한다.

const obj = new Object();
const arr = new Array();
const func = new Function();

모든 함수는 "prototype" 프로퍼티를 갖고 있다.

var func = function () {
  console.log('hello')
}

console.log(func.prototype) // [object Object {...}

위 출력문은 어떤 객체를 콘솔에 출력한다. 모든 배열이 .length 속성을 갖고 있듯이 모든 함수에는 prototype 이라는 속성이 내장 되어 있다.

생성자 함수와 prototype

각 함수가 소유한 prototype 객체는 해당 함수가 생성자 함수로 실행될 때 특별한 역할을 하게된다.

function foo () {
  console.log('Foo');
}

const something = new foo();

console.log(something.hello); // undefined

foo.prototype.hello = "hello"

console.log(something.hello); // "hello"

생성자 함수가 반환해주는 빈 객체는 Instance(인스턴스) 라고 부른다.

function Foo (name) {
  this.name = name'
}
const me = new Foo("midohree");

위 예제에서 meFoo의 인스턴스이다. 자바스크립트의 모든 인스턴스 객체는 해당 객체의 프로토타입에 존재하는 속성 및 메소드에 접근할 수 있다.

Foo : 아빠
Foo.prototype : 엄마
me : 자식 (엄마의 속성, 메소드를 물려받는다.)

Dunder proto

__proto__ (Dunder proto; 던더프로토)

던더프로토는 모든 인스턴스에 내장되어있는 속성인데, 이는 인스턴스가 엄마(프로토타입)에게 바로 접근할 수 있게 한다.

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

const me = new Person("midohree");
const result = Person.prototype === me.__proto__;

console.log(result) //
const result = Array.prototype.__proto__ === Object.prototype;
console.log(result); // true

Array / Function -> Object -> Null

__proto__를 통해 인스턴스가 상위 프로토타입에 접근 할 수 있게 했다.
Array.prototype Function.prototype 의 상위는 Object.prototype 입니다. 그럼 Object.prototype 위에는 뭐가 있을까??

Object.prototype.__proto__;

결과는 null.. 자바스크립트의 프로토타입 체인의 최상위에는 null이 존재한다.

Object.prototype.me = "midohree";

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

const myName = new Person("Kim");

console.log(myName.me); // midohree

Person 생성자 함수를 통해 myName 이라는 인스턴스가 만들어졌다. myNameme 라는 속성이 없기 때문에 myName의 엄마인 Person.prototype 을 보았지만 여기에도 me라는 속성이 없다. 그럼 Person.prototype의 엄마인 Object.prototype에 가서 찾는다. 오 엄마에게 me 라는 속성이 있다. 자식은 엄마, 엄마의 엄마의 프로퍼티와 속성까지 가져 올 수 있습니다. 그러므로 "midohree" 가 출력됩니다.

constructor

모든 prototype 에는 constructor 라는 속성이 있다. constructor는 결국 생성자 함수 자기 자신을 가르킨다.

function Person () {
  console.log("foo");
}

Person.prototype;
Person.prototype.constructor; // Person
Person.prototype.constructor.prototype.constructor; // Person
var str = 'test';

String.prototype.myMethod = function () {
  return 'myMethode';
}

console.log(str.myMethode());
console.log(str.__proto__ === String.prototype_); // true
console.log(str.prototype.__proto__ === Object.prototype); // true
console.log(String.prototype.constructor === String); // true
console.log(String.__proto__ === Function.prototype); // true
console.log(Function.prototype.__proto__ === Object.prototype); // true

참고
모든 객체는 new 생성자를 통해서 만들어진다. 그런데 문자열에도 메소드를 사용 할 수 있다. 문자열은 객체가 아닌데 왜 생성자 함수가 있는걸까..?

자바스크립트는 문자열을 내부적으로 객체처럼 만들어준다. 그래서 문자열에도 prototype을 사용 할 수 있다는 아주 신기한 사실..

var str = "123"
var str2 = new Stirng("123") // 이렇게는 사용하지 말기..
console.log(typeof str) // string
console.log(typeof str2) // object

Inheritance in Javascript

var me = {};
Object.prototype.age = 30;
console.log(me.age); // 30

meage라는 키밸류가 없다. 따라서 체인을 타고 올라가 Object.prototype 에 있는 age의 속성을 빌려쓴다.

var me = {};
Object.prototype.age = 30;
me.age = 20;
console.log(me.age); // 20

객체에게 age라는 속성을 넣어주었다. 자기 자신을 먼저 탐색하기 때문에 20이 출력됩니다.

Object.create()

function Animal () {
  this.eat = function () { console.log("EAT!"); };
}

Animal.prototype.sleep = function () { console.log("sleep"); };

function Human (name) { // new키워드를 통해 Human 안에 있는 것들이 모두 Instance가 된다.
  Animal.call(this); 
  this.name = name;
}
/*  call의 인자로 들어가는 this는 뭘까? 
	Animal 함수가 call로 실행되어  
	Animal 함수 안의 this가 Animal.call의 인자 this가 된다.

	Animal과 Human 모두에게 eat이 연결된다.
	우리는 sleep도 연결시키고 싶다. 
	Animal.prototype.sleep을 통해 Animal에 sleep을 추가해줬다.
    
	Human 에도 sleep 속성을 주고 싶다. 
	Object.create()는 지정된 프로토타입 객체 및 속성을 갖는 빈 객체를 만들어서 반환을 한다. 
	Object.create() 안에 들어가는 인자는 반환되어 나오는 단순한 객체가 아닌, 객체의 prototype을 준다. 
    
	Human.prototype = Object.create(Animal.prototype);

	빈 객체의 prototype이 Animal.prototype으로 설정된다. 
	원래 Human은 prototype속성이 있는데 이를 빈 객체로 재할당 해버렸다.
    	prototype은 constructor라는 속성이 있는데 빈 객체로 재할당 되면서 사라져 버렸다.
	그래서 constructor 속성을 다시 만들어준다. 
*/
Human.prototype.constructor = Human;

var me = new Human("midohree");
var dog = new Animal();

dog.sleep();
me.sleep();
var o = {}
o.prototype === Object.prototype;

var o = Object.create({ age: 30 })
o.prototype === { age: 30 }
console.log(o.age) // 30
console.log(o) // {}
post-custom-banner

0개의 댓글