Search
Duplicate

function instance

1. function 인스턴스 기준, function 인스턴스 생성

function 인트너스 기준

function 구분
빌트인 Function 오브젝트
function 오브젝트: function 키워드로 생성
function 인스턴스: new연산자로 생성
function 오브젝트도 인스턴스
빌트인 FUnction 오브젝트로 생성하기 때문입니다.
성격적으로는 인스턴스이지만 new연산자로 생성한 인스턴스와 구분하기위해 function 오브젝트라 칭합니다.
new 연산자로 생성하는 인스턴스는 일반적으로 prototype에 프로퍼티를 작성합니다.

function 인스턴스 생성

function Book(point){ this.point = point; }; Book.prototype.getPoint = function(){ return this.point + 200; }; var obj = new Book(100); console.log(obj.point);//100 console.log(obj.getPoint());//300
JavaScript
복사
1.
function Book(point){...}
Book 오브젝트를 생성합니다.
Book.prototype이 만들어집니다.
2.
Book.prototype.getPoint = function(){}
Book.prototype에 getPoint를 연결하고 function(){}을 할당
Book.prototype이 오브젝트이므로 프로퍼티를 연결할 수 있습니다.
3.
var obj = new Book(100);
Book()을 실행하며 인스턴스를 생성하고 생성한 인스턴스에 point값을 설정합니다.
Book.prototype에 연결된 프로퍼티를 생성한 인스턴스에 할당합니다.
4.
console.log(obj.point);
obj 인스턴스에서 프로퍼티 이름으로 값을 구해 출력
5.
console.log(obj.getPoint());
obj인스턴스의 메소드를 호출합니다.
return this.point + 200; 에서 this가 obj인스턴스를 참조합니다.
6.
함수/메소드 사용 기준
Book(): 함수
getPoint(): 메소드, prototype에 연결

2. 생성자 함수, 생성자 함수 실행 과정, 인스턴스 생성 과정

생성자 함수

new연산자와 함께 인스턴스를 생성하는 함수로 new Book()에서 Book()이 생성자 함수입니다.
new 연산자
인스턴스 생성을 제어하며 생성자 함수를 호출합니다.
생성자 함수
인스턴스를 생성 및 반환하며 인스턴스에 초기값을 설정을 합니다.
코딩 관례로 생성자 함수의 첫 문자는 대문자를 사용합니다.
Ex: new Number(), new Array(0, new Book()

생성자 함수 실행 과정

function Book(point){ this.point = point; }; Book.prototype.getPoint = function(){ return this.point; }; var obj = new Book(10);
JavaScript
복사
1.
엔진이 new연산자를 만나면 function 의 [[Construct]]를 호출하면서 파라미터 값으로 10을 넘겨 줍니다.
2.
function 오브젝트를 생성할 때 Book()함수 전체를 참조하도록 [[Construct]]에 설정하였습니다.
3.
[[Construct]]에서 인스턴스를 생성하여 반환합니다.
4.
반환된 인스턴스를 new연산자가 받아 new연산자를 호출한 곳으로 반환합니다.
5.
new라는 뉘앙스로 인해 new 연산자가 인스턴스를 생성하는 것으로 생각할 수 있지만 function 오브젝트의 [[Construct]]가 인스턴스를 생성합니다.
그렇기에 Book()이 생성자 함수입니다.

인스턴스 생성 과정

function Book(point){ this.point = point; }; Book.prototype.getPoint = function(){ return this.point; }; var obj = new Book(10);
JavaScript
복사
Book 인스턴스: { point: 10, __proto__ = { constructor: Book, getPoint: function(){}, __proto__: Object } }
JavaScript
복사
1.
new Book(10) 실행
⇒ Book오브젝트의 [[Construct]]가 호출되고 파라미터 값을 [[Construct]]로 넘겨줍니다.
2.
빈 Object를 생성하는데, 이것이 인스턴스이고 이 빈 오브젝트{ }를 하나씩 채워갑니다.
3.
오브젝트에 내부 처리용 프로퍼티를 설정합니다.
4.
오브젝트의 [[Class]]에 "Object"설정을 하기에 생성한 인스턴스 타입은 Object입니다. 그래서 Function이아닌 Object타입으로 나오는 것입니다.
5.
Book.prototype에 연결도니 프로퍼티(메소드)를 생성한 인스턴스의 [[Prototype]]에 설정하며 constructor도 같이 설정됩니다.

3. constructor 프로퍼티, constructor 비교

constructor 프로퍼티

Book function 오브젝트: { prototype: { constructor: Book } }
JavaScript
복사
생성하는 function 오브젝트를 참조합니다.
function 오브젝트를 생성할 때 설정하며 prototype에 연결되어 있습니다.
constructor가 없어도 인스턴스가 생성되지만 필요하지 않다는 의미는 아닙니다.
ES5: constructor 변경이 불가능해 생성자를 활용할 수 없습니다.
ES6: constructor 변경이 가능해져 활용성이 높아졌습니다.

constructor 비교

var Book = function(){}; var result = Book === Book.prototype.constructor; console.log("1:", result);//true var obj = new Book(); console.log("2:", Book === obj.constructor);//true console.log("3:", typeof Book);//function console.log("4:", typeof obj);//object
JavaScript
복사
1.
Book === Book.prototype.constructor
Book 오브젝트와 Book.prototype.constructor는 타입까지 동일합니다. constructor 프로퍼티는 생성하는 function 오브젝트(Book)을 참조하기 때문입니다.
2.
Book === obj.constructor;
obj의 constructor가 Book 오브젝트를 참조하기 때문에 마찮가지로 true가 출력됩니다.
3.
typeof Book
Book오브젝트의 타입은 function 타입입니다.
4.
typeof obj
obj 인스턴스의 타입은 object입니다.
function 오브젝트를 인스턴스로 생성하니 type이 object로 변경되었습니다. 그 이유는 [[Construct]]가 실행될 때 생성한 오브젝트의 [[Class]]에 'Object'를 설정하기 때문입니다. 이처럼 오브젝트 타입이 바뀐다는 것은 오브젝트의 성격과 목적이 바뀐다는것을 의미합니다. 그렇기에 일반적인 함수개념으로 접근하는 것이 아니라 인스턴스개념으로 접근해야 한다는 것입니다. 인스턴스의 가장 큰 특징은 prototype이 있으며 이 prototype에 많은 메소드들이 연결된다는 것입니다. 즉, 함수가 하나가아닌 다수라는 의미입니다.
function은 함수가 하나입니다. 하지만, 인스턴스는 함수가 다수입니다. 이런 특징의 차이로 인해 함수와 인스턴스는 다른 관점에서 봐야 합니다.

4. prototype, 상속, prototype 오브젝트 목적, 인스턴스 상속

prototype 오브젝트 목적

prototype의 목적은 연결 및 확장
prototype 확장
prototype에 프로퍼티를 연결하여 prototype 확장
Book.prototype.getPoint = function (){}
프로퍼티 공유
생성한 인스턴스에서 원본 prototype의 프로퍼티 공유
var obj = new Book(123); obj.getPoint(); 위와같이 인스턴스.메소드()를 호출하면 인스턴스의 getPoint를 호출하는 것이 아닌 Book.prototype.getPoint를 호출하는 것으로 여러 Book의 인스턴스 obj1,2,3,4가 있다면 서로가 하나의 원본(Book.prototype.getPoint)를 path만을 가져 참조하는 것입니다.
인스턴스 상속(Inheritance)
function 인스턴스를 연결하여 상속합니다.
Point.prototype = new Book()

인스턴스 상속

인스턴스 상속 방법
prototype에 연결된 프로퍼티로 인스턴스를 생성하여 상속받을 prototype에 연결합니다.
prototype-based 상속이라고도 부릅니다.
JS에서 prototype은 상속보다는 프로퍼티 연결의 의미가 더 큽니다. 인스턴스 연결도 프로퍼티 연결의 하나입니다.
ES5상속은 OOP의 상속기능이 부족합니다.
ES6에서는 Class로 상속을 할 수 있습니다. 하지만, 개발자가 Java에서 상속하듯이 키워드(class, extends...)를 사용해 상속을하지만 그 내부 코드와 로직은 기존과 크게 다르지 않습니다.
ES5 인스턴스 상속
function Book(title){ this.title = title; }; Book.prototype.getTitle = function(){ return this.title; }; function Point(title){ Book.call(this, title); }; Point.prototype = Object.create(Book.prototype, {}); var obj = new Point("javascript"); console.log(obj.getTitle());
JavaScript
복사
ES6 인스턴스 상속
class Book{ constructor(title){ this.title = title; } getTitle(){ return this.title; } }; class Point extends Book{ constructor(title){ super(title); } }; const obj = new Point("javascript"); console.log(obj.getTitle());
JavaScript
복사

5. prototype 확장 방법, 프로퍼티 연결 고려사항, constructor 연결, prototype 확장과 인트턴스 형태

prototype확장 방법

prototype에 프로퍼티를 연결하여 작성합니다.
prototype.name = value 형태
name에 프로퍼티 이름을 작성합니다
value에 JS데이터 타입을 작성합니다.
일반적으로 function을 사용
prototype에 null을 설정하면 확장이 불가능해집니다.

프로퍼티 연결 고려 사항

prototype에 연결할 프로퍼티가 많을 때
Book.prototype.name1, 2, 3 ~ N형태는 Book.prototype을 반복작성해야 하기 때문에 번거롭습니다. 그렇기에 Book.prototype = {name1: value, ...}형태로 작성합니다. 하지만, 여기서 문제는 위와같이 prototype에 Object를 할당해버리면 constructor가 지워지게 됩니다.
constructor가 지워지는 문제와 대책
{name1: value, ...} 형태로 설정한 후 prototype에 constructor를 다시 연결합니다.
function Book(){}; Book.prototype = { constructor: Book, setPoint: function(){} }; var obj = new Book(); console.log(obj.constructor);
JavaScript
복사

prototype확장과 인스턴스 형태

1.
function Book(point){};
Book오브젝트 생성
2.
Book.prototype.getPoint = function(){}
Book.prototype에 getPoint 메소드 연결
3.
var obj = new Book(100);
인스턴스를 생성하여 obj에 할당
4.
obj.getPoint()
obj 인스턴스의 getPoint() 호출
5.
인스턴스를 생성하면 prototype에 연결된 메소드를 인스턴스.메소드이름() 형태로 호출합니다.
function Book(point){ this.point= point; }; Book.prototype.getPoint = function(){ return this.point; }; var obj = new Book(100); obj.getPoint();
JavaScript
복사
obj: { point: 100, __proto__ = { constructor: Book, getPoint: function(){}, __proto__: Object } }
JavaScript
복사

6. this와 prototype, this로 인스턴스 참조, this와 prototype, prototype메소드 직접 호출

this로 인스턴스 참조

this로 메소드를 호출한 인스턴스 참조
var obj = new Book();
obj.get() 형태에서 this로 obj 참조합니다.
인스턴스에서 메소드 호출 방법
prototype에 연결된 프로퍼티가 __proto__에 설정되며 인스턴스 프로퍼티가 됩니다.
this.prototype.setPoint()형태가 아닌 this.setPoint()형태로 호출합니다.

this와 prototype

console.log("1:", this.point);
생성자 함수에서 this는 생성하는 인스턴스 참조
생성하는 인스턴스에 point 프로퍼티가 없더라도 에러가 나지 않고 undefined를 반환
obj.getPoint()
this가 메소드를 호출한 인스턴스 참조
즉, 메소드 앞에 작성한 인스턴스 참조(obj)
this.setPoint()
this가 인스턴스 참조하며 인스턴스에 있는 setPoint()호출
this.point = 100;
this가 인스턴스를 참조하며 인스턴스의 point프로퍼티에 100을 할당
function Book(){ console.log("1:", this.point); }; Book.prototype.getPoint = function(){ this.setPoint(); console.log('2:", this.point); }; Book.prototype.setPoint = function(){ this.point = 100; }; var obj = new Book(); obj.getPoint();
JavaScript
복사
[실행 결과]
1: undefined
2: 100

prototype 메소드 직접 호출

Book.prototype.getPoint();
인스턴스를 생성하지 않고 직접 메소드 호출
Book.prototype을 getPoint에서 this로 참조
obj 인스턴스에는 point가 있지만
Book.prototype에 point가 없으므로 undefined를 반환합니다.
인스턴스를 생성하여 메소드를 호출하는 것과 직접 prototype을 작성하여 호출하는것의 차이입니다.
function Book(point){ this.point = point; }; Book.prototype.getPoint = function(){ return this.point }; var obj = new Book(100); console.log(obj.getPoint()); console.log(Book.prototype.getPoint());
JavaScript
복사
[실행 결과]
100
undefined

7. prototype 프로퍼티 공유 시점

프로퍼티 공유 시점

사용사는 시점에 prototype의 프로퍼티를 공유합니다.
prototype의 프로퍼티로 인스턴스를 생성하지만 인스턴스의 프로퍼티는 원본 prototype의 프로퍼티를 참조합니다.
복사하여 인스턴스에 갖고 있는 개념이 아닙니다.
인스턴스의 메소드를 호출하면 원본 prototype의 메소드를 호출합니다.
원본 prototype에 메소드를 추가하면 생성된 모든 인스턴스에서 추가한 메소드를 사용 가능합니다. 이는 원본 prototype의 메소드를 호출하기 때문입니다.

코드를 통해 분석

function Book(){ this.point = 100; }; var obj = new Book(); console.log(obj.getPoint); Book.prototype.getPoint = function(){ return this.point }; var result = obj.getPoint(); console.log(result);
JavaScript
복사
1.
var obj = new Book();
인스턴스를 생성하여 obj에 할당합니다.
2.
console.log(obj.getPoint);
obj인스턴스에 getPoint()가 없기에 undefined이 출력됩니다.
3.
Book.prototype.getPoint = function(){ return this.point };
Book.prototype에 getPoint()를 추가합니다. 이제 앞에서 생성한 obj인스턴스에서도 getPoint() 사용가능
4.
var result = obj.getPoint();
인스턴스를 생성하는 시점이는 obj에 getPoint가 없지만 위에서 prototype에 getPoint를 추가했기에 이제 호출이 가능해집니다.
5.
return this.point
추가하더라도 this가 인스턴스를 참조합니다.
6.
이런 특징을 이용해 상황에 따라 메소드를 추가 하는 식의 동적 프로그램 개발이 가능해집니다.

8. 인스턴스 프로퍼티, 인스턴스 프로퍼티 우선 사용

인스턴스 프로퍼티

obj 인스턴스 = { point: 100, getPoint: function(){ }, //---(1) __proto__: { getPoint: function(){ }//---(2) } }
JavaScript
복사
prototpye에 연결된 프로퍼티도 인스턴스 프로퍼티(2)가 됩니다. 직접 인스턴스에 연결된 프로퍼티(1)와는 차이가 있습니다.
인스턴스의 프로퍼티(1)를 prototype으로 만든 인스턴스 프로퍼티(2)보다 먼저 사용합니다.
인스턴스마다 값을 다르게 가질수 있으며 인스턴스를 사용하는 중요한 목적입니다.
function Book(point){ this.point = point; }; Book.prototype.getPoint(){ console.log(this.point); } var obj1 = new Book(100); var obj2 = new Book(200); var obj3 = new Book(300); obj1.getPoint();//100 obj2.getPoint();//200 obj3.getPoint();//300
JavaScript
복사

인스턴스 프로퍼티 우선 사용

1.
Book.prototype.getPoint(){return 100;}
prototype에 getPoint를 연결하며 인스턴스의 getPoint()호출 시 100을 반환합니다.
2.
obj.getPoint = function(){ return this.point; };
생성한 인스턴스에 getPoint를 연결합니다.
함수가 호출되면 200을 반환합니다.
3.
obj 인스턴스 구성 형태
obj 인스턴스 = { getPoint: function(){return this.point;}, _proto_:{ getPoint: function(){return 100;} } }
JavaScript
복사
4.
obj.getPoint();
obj 인스턴스의 getPoint() 호출
prototype의 getPoint()가 호출되지 않고 인스턴스의 getPoint()가 호출됩니다.
인스턴스의 연결한 프로퍼티를 먼저 사용하기 때문입니다.
5.
인스턴스 프로퍼티는 공유되지 않습니다.
6.
Class 접근
설계가 중요하며 OOP개념 이해 필요
function Book(point){ this.point = point; }; Book.prototype.getPoint(){ return 100; } var obj = new Book(200); obj.getPoint = function(){ return this.point; }; console.log(obj.getPoint());//200
JavaScript
복사