Function Instance
Function 의 구분
- built-in Function Object - 엔진 제공
- Function 키워드로 생성하는 Function Object
- new 연산자로 생성하는 Function Instance
Function Object라 말하고 있지만, Function Object도 결국 Instance다. built-in Function Object로 생성하기 때문이다. 성격적으로는 인스턴스지만, new 연산자로 생성한 인스턴스와 차이가 있기 때문에, 앞에서는 Function Object로 말했다.
new Function
new
연산자로 생성하는 Function Instance는 prototype에 프로퍼티를 작성한다.
function Book(point) {
this.point = point;
}
Book.prototype.getPoint = function () {
return this.point + 200;
};
var obj = new Book(100);
console.log(obj.point);
console.log(obj.getPoint);
-
엔진은 Book이라는 function object를 만든다. 이때 book Object의 prototype이 만들어진다.(엔진이 자동으로 만들어줌)
- prototype 또한 Object다.
-
Book.prototype.getPoint = function(){}
- prototype 또한 Object이기 때문에 위와 같이 프로퍼티를 연결할 수 있다.
- Book.prototype에 getPoint 프로퍼티를 만들고, function Object를 할당한다.
-
new Book실행
- Book의 인스턴스를 생성하고, 생성한 인스턴스를 실행해서 point를 할당하게 된다.
- 이때 내부의 this는 인스턴스를 참조하게 된다.
- Book.prototype에 연결된 프로퍼티를 생성한 인스턴스에 연결한다.
- 그리고 이러한 인스턴스를 return 하게 된다.
용어 정리
-
생성자 함수
new book()
에서book()
이 생성자 함수다. new 연산자와 함께 인스턴스를 생성하는 함수를 "생성자 함수"라고 한다.- 생성자 함수는 인스턴스를 생성하고 반환한다.
- 인스턴스에 초기값을 설정해준다.
-
new 연산자
- 인스턴스 생성을 제어한다.(new 자체가 인스턴스를 생성하는 것이 아니다.)
- "생성자 함수를 호출"하고 생성자 함수가 인스턴스를 반환해준다.
생성자 함수 실행과정
function Book(point) {
this.point = point;
}
Book.prototype.getPoint = function () {
return this.point + 200;
};
var obj = new Book(100);
-
엔진이 function Book()의 function 키워드를 만나면서 function Object 생성한다.
- 이때, 엔진은
[[Construct]]
에 Book() 함수 전체를 참조할 수 있도록 참조를 해놨다.
- 이때, 엔진은
-
엔진이
new Book(100)
을 만난다.- 엔진은
new
키워드를 만나면 function Object의 내부 프로퍼티[[Construct]]
를 호출하게 되고(결국 함수 그 자체???를 호출), 파라미터 값으로 100을 넘겨준다.
- 엔진은
-
[[Construct]]
가 호출되면, 인스턴스를 생성해서 반환한다. -
반환된 인스턴스를
new
연산자가 받게된다. 그리고 new 연산자는 obj에 인스턴스를 할당한다.
"Instance" 생성 과정
function Book(point) {
this.point = point;
}
Book.prototype.getPoint = function () {
return this.point + 200;
};
var obj = new Book(100);
new Book(100)
을 실행하면, 엔진은 Book Function Object의[[Construct]]
를 호출하고 파라미터 값을[[Construct]]
에 넘겨준다.[[Construct]]
는 우선 빈 오브젝트를 생성하고 채워나가기 시작한다.- 이 빈 오브젝트가 인스턴스다.
- 엔진은 이 빈 오브젝트에 내부 처리용 프로퍼티를 설정해 나간다.
- 공통 프로퍼티 설정
- 선택적 프로퍼티 - 함수에 필요한 내부 프로퍼티를 설정
[[Class]]
프로퍼티에"Object"
를 설정하는데, 따라서 생성한 인스턴스 타입은 Object가 된다.[[Prototype]]
에는 Book.prototype에 연결된 프로퍼티(메소드)를 설정한다.즉 인스턴스에서 프로토타입에 연결된 메서드들을 가지게 된다.- 이때 인스턴스
__proto__
밑의constructor
도 같이 설정한다.(function object)(생성자)함수 자체를 참조하게 된다.
위의 과정의 결과
"Book인스턴스" : {
point = 100,
__proto__ = {
constructor : Book,
getPoint : function(){},
__proto__ : Object
}
}
"function object"의 constructor
"Book_Function_Object" : {
prototype : {
constructor : Book
}
}
- constructor 프로퍼티는 생성하는 function Object를 참조한다.
- 이것은 function Object를 생성할 때 설정된다.(엔진이 해줌)
- constructor 프로퍼티는 prototype에 연결되어 있다.
- constructor 프로퍼티의 값은 Book function Object 전체를 참조한다.
- ES5 기준에서는 constructor변경이 불가능하여 생성자를 활용할 수 없었지만, ES6부터는 constructor 변경이 가능해졌다. (생성자 함수에 코드를 추가할 수 있게 되었다. 역시 ES6를 사용해야만 가능하다)
function object의 constructor에 대해서
// Function Object이자 생성자 함수다
var Book = function(){}
var obj = new Book();
// function object의 constructor와 Book함수 자체를 비교
console.log(Book === Book.prototype.constructor) //=> true
// 인스턴스의 __proto__.constructor와 Book함수 자체를 비교
console.log(Book == obj.constructor) //=> true
console.log(typeof Book) //=> function
console.log(typeof obj) //=> object
-
console.log(Book === Book.prototype.constructor) //=> true
- Book Object와 Book.prototype.constructor가 타입까지 같다는 뜻
- Book (function)Object를 생성할 때, Book.prototype.constructor가 Book Object를 참조하기 때문이다.
-
console.log(Book == obj.constructor) //=> true
- obj(인스턴스)의 constructor가 Book (function)Object를 참조한다.
-
typeof Book & typeof obj
- 오브젝트의 타입이 바뀐다는 것은, 오브젝트 성격과 목적이 바뀐 것을 뜻한다. 따라서 다른 관점에서 접근해야 한다.
- new 를 통해 function에서 object로 바뀌었다.(사실 function도 js에선 object의 하위 레벨이다) object로 바뀌었다는 것은 "인스턴스"임을 의미한다. 인스턴스의 가장 큰 특징은 프로토타입을 가지며, 이 프로토타입에는 많은 메소드들이 연결된다는 것이다. 즉, 함수가 하나가 아니라 다수가 되었다. 이게 함수와 인스턴스의 차이다.
함수와 인스턴스의 차이
사실 자바스크립트에서 built-in Function은 built-in Object의 하위 개념으로 분류하고 있다. typeof
연산자가 object
를 반환하는 것은 인스턴스이며 function
을 반환하는 것은 함수라고 보면 된다.
인스턴스의 가장 큰 특징은, 프로토타입이 있으며 프로토타입에는 여러가지 메소드가 연결될 수 있다는 것이다.
new
키워드를 사용하여 function으로 인스턴스를 만들 수 있는데, 하나의 함수로 만든 인스턴스임에도 불구하고, 여러개의 함수(메소드라 부르는 것이 더 타당함)가 존재할 수 있다는 것이다.
prototype Object
JS내의 모든 객체는, 자신의 상위 객체와 연결되어 있다. 이러한 상위 객체를 Prototype Object 또는 줄여서 prototype이라고 한다.
prototype의 목적
-
프로퍼티 공유 prototype 객체는 생성자 함수에 의해 생성된 각각의 객체에 공유 프로퍼티를 제공해 줄 수 있다. (생성한 인스턴스에서 원본 prototype의 프로퍼티를 공유할 수 있다.)
var obj = new Book(1234)
로 인스턴스를 생성하고,obj.getPoint()
를 하게 되면, 인스턴스의 getPoint를 호출하는 것이 아니라,Book.prototype.getPoint
를 호출하게 된다.- obj 인스턴스 내에는 Book.prototype에 접근할 수 있는 경로가 저장되어 prototype의 메소드 호출이 가능하다.
- 이것 말고, 공유에는 다른 기능??이 있다 나중에 살펴보자
-
prototype 확장 prototype 객체에 프로퍼티를 추가하여 prototype을 확장할 수 있다.
Book.prototype.getPoint = function(){}
처럼 prototype을 확장 할 수 있다.
-
Instance 상속 function 인스턴스를 연결하여 상속을 구현한다.
Point.prototype = new Book()
자바스크립트의 상속은 프로토타입 확장의 개념이라고 보면 된다.