자바스크립트는 프로토타입 기반 객체지향 프로그래밍 언어이다. 자바스크립트의 모든 객체는 자신의 부모 역할을 담당하는 객체와 연결되어있다. 그리고 이것은 마치 객체 지향의 상속 개념과 같이 부모 객체의 프로퍼티 또는 메소드를 상속받아 사용 할 수 있게 한다. 이러한 부모 객체를 Prototype(프로토타입) 이라고 한다.
const obj = {};
const arr = [];
const func = function () {};
흔히 우리는 위와 같이 객체를 생성한다. 하지만 자바스크립트는 사실상 내부적으로 생성자 함수를 이용해 만드는 것과 동일하게 객체를 생성한다.
const obj = new Object();
const arr = new Array();
const func = new Function();
var func = function () {
console.log('hello')
}
console.log(func.prototype) // [object Object {...}
위 출력문은 어떤 객체를 콘솔에 출력한다. 모든 배열이 .length
속성을 갖고 있듯이 모든 함수에는 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");
위 예제에서 me
는 Foo
의 인스턴스이다. 자바스크립트의 모든 인스턴스 객체는 해당 객체의 프로토타입에 존재하는 속성 및 메소드에 접근할 수 있다.
Foo
: 아빠
Foo.prototype
: 엄마
me
: 자식 (엄마의 속성, 메소드를 물려받는다.)
__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
__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
이라는 인스턴스가 만들어졌다. myName
에 me
라는 속성이 없기 때문에 myName
의 엄마인 Person.prototype
을 보았지만 여기에도 me
라는 속성이 없다. 그럼 Person.prototype
의 엄마인 Object.prototype
에 가서 찾는다. 오 엄마에게 me
라는 속성이 있다. 자식은 엄마, 엄마의 엄마의 프로퍼티와 속성까지 가져 올 수 있습니다. 그러므로 "midohree"
가 출력됩니다.
모든 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
var me = {};
Object.prototype.age = 30;
console.log(me.age); // 30
me
에 age
라는 키밸류가 없다. 따라서 체인을 타고 올라가 Object.prototype
에 있는 age
의 속성을 빌려쓴다.
var me = {};
Object.prototype.age = 30;
me.age = 20;
console.log(me.age); // 20
객체에게 age
라는 속성을 넣어주었다. 자기 자신을 먼저 탐색하기 때문에 20
이 출력됩니다.
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) // {}