이력
- 2022.03.16 1절 포스팅
- 2022.03.16 6절 까지 포스팅
- 2022.03.18 14절 까지 포스팅
모든 내용을 상세히 담으려 하지 않았습니다.
제가 모르는 부분이나, “이런 것도 있었어?” 하는 부분, 중요하다고 생각되는 부분,
다시 한번 되새기고 싶은 부분만 기록했습니다.
읽어주셔서 감사합니다.
26.1 Function 인스턴스 생성#
- Function은 Function 오브젝트와 인스턴스로 나눕니다. funcion 키워드를 마나 생성한 것이 function 오브젝트이고 new 연산자로 생성한 것이 인스턴스입니다.
1
2
3
4
5
| function sports(value) {
this.value = value;
}
sports.prototype.amount = 456;
var sportsObj = new sports(123);
|
- sports가 Function 오브젝트여야 new 연산자로 인스턴스를 생성할 수 있으며 함수로 호출할 수 있으며 prototype에 프로퍼티를 연결할 수 있습니다.
- sports.prototype 은 어디로?
- sports 오브젝트 구조를 보면 prototype이 있고 그 안에 construct가 있습니다. 그런데 sports 인스턴스를 보면 __proto__에 constructor만 있는 것을 알 수 있습니다. 이를 통해 오브젝트의 prototype에 연결된 프로퍼티로 인스턴스를 생성한다는 것을 알 수 있습니다.
- 또한, 인스턴스는 prototype가 없어 프로퍼티를 연결할 수 없게 됩니다.
26.2 생성자 함수#
1
2
3
4
5
| function Baseball(point) {
this.point = point;
}
Baseball.prototype.player = 9;
var baseballObj = new Baseball(7);
|
- new 연산자를 보기 전 까지는 일반 함수인지 생성자 함수인지 알 수 없다. 관례상 생성자 함수는 대문자로 시작한다.
- new 연산자는 인스턴스 생성을 제어, 생성자 함수는 생성하여 반환하는 역할을 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| new 연산자 생성자 함수 실행 과정
1. 엔진이 new 연산자를 만난다.
- 생성자 함수를 표현식으로 인식합니다.
2. 표현식을 평가하고 결과를 반환합니다.
3. 결과값이 오브젝트가 아니면 더 이상 처리하지 않습니다.
4. 평가한 오브젝트의 [[Constructor]]를 호출합니다.
5. [[Constructor]]에서 인스턴스를 생성해 반환합니다.
6. 5번에서 생성된 인스턴스를 반환합니다.
[[Constructor]] 내부 함수의 인스턴스 생성 과정
1. 새로운 오브젝트를 생성합니다.
2. 오브젝트에 js 내부 처리용 메소드를 설정합니다.
3. 오브젝트의 [[Class]]에 'Object'를 설정합니다.
4. Baseball 오브젝트의 [[Prototype]]의 프로퍼티를 생성한 오브젝트의 [[Prototype]]에 설정합니다.
5. 생성한 오브젝트와 [[Constructor]]를 호출할 때 넘겨준 파라미터로 Baseball 오브젝트의 [[Call]]을
호출합니다.
- 복잡하고 많은 처리를 거치지만 자세히 다루지는 않습니다.
- [[Call]] 이외에도 [[Code]], [[Scope]] 등이 설정되어 있지 않습니다. EC를 생성하면서 Baseball
오브젝트와 내부 프로퍼티, [[Constructor]]를 호출할 때의 파라미터 값을 파라미터로 넘겨줍니다.
[[Constructor]]에서 생성한 오브젝트에 실행결과를 설정합니다. EC가 종료되면 생성한 오브젝트를
반환하여 baseballObj에 할당합니다.
|
26.3 constructor 프로퍼티#
- Constructor는 Function 오브젝트를 참조하고 있으므로 두개는 같다.
1
2
3
4
5
6
7
8
9
10
11
12
| var sports = function() {};
js.log(sports === sports.prototype.constructor);
var sportsObj = new sports();
js.log(sports.constructor === sports);
js.log(typeof sports);
js.log(typeof sportsObj);
// true
// true
// function
// object
|
- 마지막에 object로 출력되는 것은 [[Constructor]]가 실행될 때 새로운 오브젝트를 생성하면서 [[Class]]에 ‘Object’를 설정하기 때문입니다.
26.4 constructor로 인스턴스 생성#
1
2
3
4
5
6
7
8
9
10
11
12
13
| function Sports(){};
var sportsObj = new Sports();
try {
new sportsObj();
} catch (e) {
js.log('인스턴스 생성 불가');
}
var consObj = new sportsObj.constructor();
js.log(typeof consObj);
// 인스턴스 생성 불가
// object
|
- 생성자 함수가 아니면 인스턴스를 생성할 수 없으므로 실패한다.
- constructor()는 sports 오브젝트를 참조하고 있으므로 인스턴스가 생성되지만 constructor()를 호출하여 인스턴스를 만들지는 않는다.
26.5 인스턴스 프로퍼티 존재 체크#
1
2
3
4
5
6
| var sports = function(){};
var sportsObj = new sports();
js.log(sports.call);
js.log(sportsObj.call);
debugger
|
- sportsObj 인스턴스에서 Function 오브젝트의 call 메소드를 호출할 수는 없지만, Object 오브젝트의 메소드를 호출할 수 있습니다.
- sports Function 오브젝트로 sportsObj를 생성했는데 Function 오브젝트의 메소드를 호출할 수 없는 것은 [[Constructor]]가 실행될 때 생성하는 인스턴스 타입 [[Class]]에 Object를 설정하기 때문입니다. sportsObj 타입이 object이므로 Object 오브젝트 메소드가 설정되고 Function 오브젝트 메소드는 설정되지 않습니다.
- new 연산자와 생성자 함수로 인스턴스를 생성하는 것은 Function 오브젝트의 프로퍼티와 메소드를 공유하기 위해서입니다.
26.6 prototype 오브젝트#
26.6.1 프로퍼티를 연결하여 오브젝트 확장#
- prototype이 오브젝트이므로 프로퍼티를 연결할 수 있습니다.
26.6.2 생성한 각 인스턴스에서 prototype에 연결된 프로퍼티 공유(share)#
26.6.3 다른 Function 인스턴스를 상속받아 오브젝트 통합#
- prototype에 인스턴스를 연결하여 상속을 구현합니다. 하나만 연결할 수 있습니다. 연쇄적인 계층구조로 연결될 수 있습니다. 프로토타입 체인이라고 합니다.
26.7 Function 오브젝트 확장과 인스턴스#
- prototype에 오브젝트( {name: value })를 연결할 수 있으며 null을 설정할 수도 있습니다. prototype의 기본타입이 오브젝트이므로 null을 설정한다는 것은 더 이상 프로퍼티를 연결하지 않겠다는 의도입니다.
1
2
3
4
5
6
7
| var sports = function() {};
sports.prototype.getMember = function(member) {
js.log('파라미터: ' + member);
};
var sportsObj = new sports();
sportsObj.getMember(123);
debugger;
|
- sports 오브젝트 안에 Function 오브젝트를 연결하여 오브젝트를 확장한 모습입니다.
26.8 prototype에 프로퍼티 연결 방법, 목적#
1
2
3
4
5
6
7
8
9
| 1) sports.prototype['get'] = function(){};
2) sports.prototype.get = function(){};
3) sports.prototype.[get] = function(){};
// get 이름의 변수가 존재해야 한다.
4) sports.prototype = {
get: function(){}
}
// 다수의 프로퍼티를 할당할 때 사용되며 기존에 prototype에 연결된 프로퍼티가 지워집니다.
|
- prototype에 메소드를 연결하는 것은 원본에 무언가를 추가하여 인스턴스를 만들어 사용하겠다는 것입니다.
26.9 prototype에 오브젝트 연결 및 고려사항#
1
2
3
4
5
6
7
8
| var book = function(){};
book.prototype = {
constructor: book,
set: function(){},
value: 12345
}
var bookObj = new book();
js.log(bookObj.constructor);
|
- 블록으로 프로퍼티를 설정하는 경우 constructor가 지워지는 것을 유의해야합니다. 일반적으로 사용하지 않으므로 문제는 없으나 필요할 때는 위와같이 설정해줘야합니다.
- 지워지면 sportsObj.__proto__.__proto__에 있는 Object의 constructor가 호출됩니다.
26.10 prototype과 this#
1
2
3
4
5
6
7
8
9
10
11
| function sports() {
js.log(this.member);
}
sports.prototype = {
member: 123,
getMember: function(value) {
js.log(this.member + value);
}
};
var sportsObj = new Sports();
sportsObj.getMember(500);
|
- this는 함수를 호출할 때 함수 앞에 작성한 오브젝트(인스턴스)를 참조합니다.
- getMember 메소드의 this는 sportsObj를 가르킵니다. sportsObj는 sports.prototype을 공유하므로 getMember 메소드내의 this.member는 sports.prototype.member와 동일하므로 member에 접근가능해진다.
26.11 prototype 프로퍼티 공유 시점#
- 인스턴스를 생성할 때 생성자 함수의 prototype에 연결된 프로퍼티를 복사하는 것이 아니라 공유하는 것입니다. 복사하면 메모리도 더 차지하게 됩니다.
26.12 prototype의 프로퍼티 값 변경#
26.13 인스턴스에 프로퍼티 추가#
- 인스턴스에 프로퍼티를 추가하면 인스턴스마다 다른 값을 가질 수 있으며 prototype의 프로퍼티보다 먼저 검색됩니다.
26.14 인스턴스 프로퍼티 추가 고려사항#
1
2
3
4
5
6
7
8
| var sports = function(){};
sports.prototype.soccer = {member: 123};
var sportsObj = new sports();
sportObj.soccer.member = 456;
// sportsObj.soccer = {member: 456};
js.log(sportsObj.soccer.member);
js.log(spots.prototype.soccer.member);
|
- 인스턴스 프로퍼티에만 추가하려면 주석처리된 부분과 같이 블록으로 설정하거나 this를 사용해야 한다.