이력

  • 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);

fig.1

  • ​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를 사용해야 한다.