상세 컨텐츠

본문 제목

[JavaScript] 함수와 프로토타입 체이닝(3)

개발공부/JavaScript

by 임우찬 2019. 9. 11. 10:47

본문

 

 

*생성자 함수란?

- 자바스크립트의 객체를 생성하는 역할을 한다.

- C++ 이나 자바같은 객체지향 언어에서와 다르게 기존함수에 new연산자를 붙여 호출하면 해당 함수는 생성자 함수로 동작한다.

- 이 이유 때문에 원치않는 생성자 함수로 동작할 수 있다.

(이 때문에, JS 스타일 가이드에 따르면 특정 함수가 생성자 함수로 정의되어 있음을 알리기 위해 함수이름 첫 문자를 대문자로 쓰기를 권한다.)

앞의 내용을 다시한번 정리해보자.

* 객체란 : 서로 연관된 함수와 변수를 그룹핑한 그릇으로, 객체 내의 변수를 property 함수를 method라고 부른다.

* 생성자란: 객체를 만드는 역할을 하는 함수다.

* new를 생성자 앞에 붙일 경우, 객체를 생성하여 반환한다.(이러한 작업을 "초기화"라고 한다.)


8-(3) 생성자 함수를 호출할 때 this 바인딩.

- 우선 일반 함수 호출 방식에서 this 바인딩과 다르게 동작한다.

* 생성자 함수가 동작하는 방식

1. 빈 객체 생성 및 this 바인딩.

- 생성자 함수 코드 실행 전 빈 객체가 생성된다.( 이 객체가 생성자 함수가 생성하는 객체이다.)

- 생성자 함수가 생성한 객체는 자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 객체를 자신의 프로토타입 객체로 설정한다.(JS 객체생성의 규칙이다.)

2. this를 통한 프로퍼티 생성

- 함수코드 내부에서 this를 사용해, 앞에서 생성된 빈 객체에 동적으로 프로퍼티나 메서드를 사용 가능하다.

3. 생성된 객체 리턴

- 특별하게 리턴문이 없을 경우, this로 바인딩된 새로 생성한 객체를 리턴한다.

- 리턴값이 새로 생성한 객체가 아닌 다른 객체를 반환하려는 경우,

생성자 함수를 호출했어도 this가 아닌 해당 객체를 리턴한다.

ex)

- Person 이라는 생성자 함수를 정의하고 이를 통해 foo 객체를 만들었다.

- Person 함수를 new로 호출하면 Person() 은 생성자 함수로 동작한다.

* Person() 함수가 생성자로 호출되면 함수코드 실행 전에 빈 객체가 생성된다.

여기서 생성된 빈 객체는 person() 생성자 함수의 prototype프로퍼티가 가리키는

객체 [[prototype]] 링크로 연결하여 자신의 프로토타입으로 설정하게 된다.

이렇게 설정 된 객체는 생성자 함수에서 사용하는 this 로 바인딩된다.

이를 그림으로 나타내면 다음과 같다.

- Person() 생성자 함수 내부의 this는 빈 객체로 바인딩된다.

* 객체 리터럴 방식과 생성자 함수를 통한 객체 생성방식의 차이

- [[Prototype]]에 차이가 있다.

- 객체 리터럴 방식의 경우 자신의 prototype 객체는 Object.prototype이다.

- 생성자 함수 방식의 경우, 위 예시로는 Person.protype 이다.

(위 차이가 발생하는 이유는 JS 객체생성 규칙 때문에 발생한다.)


*다시

- JS의 객체생성 규칙

- JS의 객체는 자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 객체를 자신의

프로토타입 객체로 설정한다.

- 그러므로, 리터럴 방식으로 생성한 객체의 생성자 함수는 Object()이다.

* JS에서는 일반함수와 생성자 함수의 구분을 하지 않는다.

- 따라서 생성자 함수는 첫 문자를 대문자로 암묵적으로 표기한다.

- new를 붙여 함수를 호출하면, 생성자 함수로 동작한다.


8-(4) call과 apply 메서드를 이용한 명시적 this 바인딩.

- JS는 이러한 내부적 this 바인딩 외에도 this를 특정 객체에 명시적으로 바인딩시키는 방법을 제공한다.

- 이 메서드들 또한 Function.Prototype의 메서드이다.

- apply() 메서드는 결국 호출하는 주체가 함수이다. (본질적 기능은 함수호출이다.)

- 가령, Person.apply() 이렇게 호출할 경우 기본적 기능은 Person이라는 함수를 호출하는 것이다.

기본 형식

- function.apply(thisArg,argArray);

- 첫 번째 인자 thisArg는 apply 메서드를 호출한 함수 내부에서 사용한 this에 바인딩할 객체를 의미한다.

- 두 번째 argArray인자는 함수를 호출할 때 넘길 인자들의 배열을 의미한다.

- 정리

- 두 번째 인자인 argArray 배열을 자신을 호출한 함수의 인자로 사용하되, 이 함수 내부에서 사용된 this는 첫 번째 인자인 thisArg 객체로 바인딩 해 함수 호출하는 기능을 한다.

* call과 apply 메서드의 차이점

- call() 메서드는 두 번째 인자에서 배열 형태로 넘긴 것을 각각 하나의 인자로 넘긴다.

- apply() 메서드는 두 번째 인자에서 배열 형태로 넘긴 것을 각각 배열로 넘긴다.

- 그 외 기능은 같다.

예시)

- Array.prototype.slice.apply(arguments); 의 결과값은 apply()의 두 번째 인자로, slice()메서드를 호출할 때 사용할 인자를 넘기지 않는다.

- 그 결과, arguments 객체로 인자없이 slice()를 호출한 형태가 된다.

- Slice() 메서드는 인자가 없을 경우에 이 메서드를 호출한 배열을 복사해 새로운 배열을 만든다.

(args에 리턴해준다.)

- 두 객체는 _proto_에서 차이가 나타난다.(Object, Array)

- 결론적으로,

Array.prototype.slice() 메서드를 호출하라. 이 때 this는 arguments 객체로 바인딩해라.

이 말의 뜻은 결국 arguments 객체가 Array.prototype.slice()메서드를 자신의 메서드인 양

arguments.slice()와 같은 형태로 호출하라는 뜻이다.


 

관련글 더보기

댓글 영역