-
2021_12_14 생성자 함수에의한 객체 생성IT/js 2021. 12. 14. 19:12
딥다이브 생성자 함수에 의한 객체 생성 17장 정리
- 10장 “객체 리터럴”에서 객체 리터럴에 의한 객체 생성 방식을 살펴보았음
- 객체 리터럴에 의한 객체 생성 방식은 가장 일반적이고 간단한 객체 생성 방식
- 다양한 방법으로 생성할 수 있음
- 17장에서는 여러 생성방식 중 생성자 함수를 사용하여 객체 생성 방식 설명
- 정리하자면 객체리터럴 vs 생성자 함수 사용 장단점 비교하는 장이 되겠다.
1. Object 생성자 함수
- new 연산자와 함께 Object 생성자 함수를 호출하면 빈 객체를 생성하여 반환.
- 빈 객체를 생성한 이후 프로퍼티 또는 메서드를 추가하여 객체를 완성할 수 있다.
const person = new Object(); person.name = 'Lee' person.sayhello = function(){ console.log('Hello My name + this.name); } console.log(person); // {name: "Lee", sayHello: f} person.sayhello(); // Hello My name Lee1.1. 예제를 살펴보자면 person이라는 이름을 가진 생성자 Object 객체를 생성
1.2. name이라는 메서드에 문자열을 담을 수 있음
1.3. sayhello 라는 메서드에 함수를 담을 수 있음
1.3.1. sayhello 함수 내부에 this를 사용하여 person의 name을 가지고올 수 있음
1.4. person을 출력 시 메서드를 출력
1.5. person.sayhello() 메서드 함수 출력 시 함수 결과값 출력
- Object 생성자 함수 외에도 String, Number, Boolean, Function, Array, Data, RegExp, Promise 등의 빌트인 생성자 함수를 제공 (RegExp - 정규표현식)
- Object 생성자 함수는 빈 객체 생성하는 것임
2. 생성자 함수
- 객체 리터럴에 의한 생성 방식은 직관적이고 간편
- but 객체 리터럴에 의한 객체 생성 방식은 단 하나의 객체만 생성
- 따라서 동일한 프로퍼티를 갖는 객체를 여러 개 생성해야 할 경우 매번 같은 프로퍼티 기술 해야해서 비효율
const circle1 = { radius:5, getDiamter(){ return 2 * this.radius; } }; console.log(circle1.getDiameter()); // 10 const circle2 = { radius:10, getDiamter(){ return 2 * this.radius; } }; console.log(circle2.getDiameter()); // 20- 프로퍼티는 객체마다 값이 다를 수 있지만 메서드 내용이 동일한 경우가 일반적
- 위 예제의 circle1 객체와 circle2 객체는 프로퍼티 구조가 동일함
- radius 프로퍼티의 값은 객체마다 다를 수 있지만 getDiameter 메서드는 완전히 동일하다.
- 한 두개라면 문제가 안되겠지만 수십 개의 객체를 만들경우 객체 리터럴에 의한 객체 생성은 문제가 크다~
3. 생성자 함수에 의한 객체 생성 방식의 장점
- 생성자 함수에 의한 객체 생성방식은 객체를 생성하기 위한 템플릿(클래스) 처럼 생성자 함수를 사용하여 프로퍼티 구조가 동일한 객체 여러 개를 간편하게 생성 -> 인자로 데이터 값 넣으면 재활용 할 수 있으니 쉽다
- 정리하자면
3.1. 함수하나 만들기
3.2. 함수인자값에 다른데이터 넣고 new 를 붙여서 변수안에 넣기
3.3. 객체를 손쉽게 재활용 가능
- 당연하게도 new 연산자와 함께 생성자 함수를 호출하지 않으면 일반 함수로 작동
4. 생성자 함수 인스턴스 생성 과정
- 생성자 함수 몸체에서 수행해야 하는 것이 무엇인지 생각
- 생성자 함수의 역할은 프로퍼티 구조가 동일한 인스턴스 생성, 생성된 인스턴스를 초기화 및 할당
- 인스턴스 생성은 필수, 인스턴스 초기화는 옵션
- js 엔진은 new 연산자와 함께 함수를 호출하면 암묵적인 처리로 인스턴스 생성하고 초기화 후 반환
4.1. 인스턴스 생성과 this 바인딩
- 암묵적으로 빈 객체가 생성 -> 생성자 함수가 생성한 인스턴스
- 생성된 빈 객체(인스턴스)는 this에 바인딩
- 생성자 함수 내부에 this가 생성자 함수가 생성할 인스턴스를 가르키는 이유가 이것임
- 런타임 이전에 실행되는 것
* 바인딩은 this가 가르칠 객체의 메모리 공간을 미리 잡고 연결 해주는 것 (런타임 이전 실행)
4.2. 인스턴스 초기화
- this 바인딩도 암묵적으로 처리가 된다.
- 정리하면 원래는 this 바인딩을 하고 생성해야할 인스턴스 주소값을 확보한 다음 내가 초기화하고 할당 다해야하는데
- js에서 암묵적으로 this 바인딩을 해주니깐 나는 바로 인스턴스 초기화하고 값할당 하고 하기만 하면된다.
4.3. 인스턴스 반환
- 암묵적으로 this가 바인딩되고 작업한 것 조차도 메모리에 잡히기 때문에
- new 를 붙여서 생성자 함수로 만들면 this가 유유히 사라진다. (데이터도 반환)
- 하지만 return 값을 넣으면 this가 열심히 잡아놓은 공간을 무시하고 return 값이 반환된다.
( 함수 내부 내용을 넣어봤자 return 넣어서 날려버릴 수 있다 단, 원시값 넣으면 다시 this 반환함 )
- 결론은 생성자 함수 사용했으면 어지간해선 return문 생략하자
5. 내부 메서드 call, construct
- 함수 선언문 또는 함수 표현식으로 정의한 함수는 일반적인 함수로서 호출할 수 있는것은 물론 생성자 함수로도 호출할 수 있음
- 물론 생성자 함수는 new 연산자와 함께 호출
- 함수는 객체이므로 일반 객체와 동일하게 동작할 수 있음
- 함수 객체 = 일반 객체 (내부 슬롯, 내부 메서드)
- 그냥 한마디로 일반 함수도 내부 메서드로 호출해서 잘 사용할 수 있다.
- 차이점은 일반 함수면 Call, new 넣은 생성자 함수면 Construct가 호출된다.
- 모든 함수는 callable을 가지고 있음
- 생성자 함수는 Construct를 가지고 있음
- 따라서 모든 함수는 Construct, non-Construct 로 나뉜다.
- 즉 모든 함수는 객체를 호출 할 수 있지만 생성자와 그냥 함수로 나뉜다.

6. Construct, non-Construct 구분
- Construct : 함수 선언문, 함수 표현식, 클래스
- non-Construct : 메서드, 화살표 함수, function이 없는 축약문(메서드가 된다.)
- 고로 non-Construct 는 생성자 함수로 호출하면 에러 발생
7. new 연산자
- 일반 함수와 생성자 함수는 특별한 형식적 차이는 없음 new 붙이면 생성자 함수로 동작할뿐
- 생성자 함수는 return을 쓰더라도 { } 감싸주자 그래야 호출된다.
- 일반 함수의 this는 함수 내부가 아닌 전역 window를 가리킨다.
- 표기에 별 차이가 없기 때문에 그래서 생성자 함수는 보통 첫 문자를 대문자로 기술한다.
8. new.target
- 생성자 함수가 new 연산자 없이 호출될 수 있으니 ES6 에서 new.target 지원
- 메타 프로퍼티라 불리고 IE는 지원하지 않는다..
- 함수 내부에서 new.target 사용하면 new 연산자와 함께 생성자 함수로 호출되었는지 확인 할 수 있다.
- new 연산자랑 new.target 같이 사용하면 new.target은 함수 자신을 가르킨다.
- 만약 new가 없는데 new.target 사용하면 undefined 나온다.
- 그러므로 new가 있는지 없는지 판별가능
- 실수로 new를 빼먹었어도 new.target이 있으면 생성자 함수로서 호출되기는 한다. (거진 예외처리)
- IE에서 안되니깐 다른 문법으로는
- 아래 방식으로 예외처리를 진행 할 수 있다. ( new.target도 함수를 가르키니, this로 판별 가능)
function Circle(radius){ if(!(this instanceof Circle){ return new Circle(radius); } }- instanceof 연산자는 19장 프로토타입에서 살펴볼 것
9. 마무리
- 대부분의 빌트인 생성자 함수 String, Number, Boolean, Function, Array, Data, RegExp, Promise 등 생성자 함수는 new가 잇냐 없냐에 따라 적절한 값을 반환한다
- Object는 new가 있건 없건 동일하게 작동하니 어지간해선 쓰지말자.
- Object가 아닌 생성자 함수를 사용할땐 반드시 new의 유무를 확인하거나 예외처리를 진행하자
let obj = new Object(); console.log(obj); // {} obj = Object(); console.log(obj); // {} --------------------------- const str = String(123); console.log(str, typeof str); // 123 string const str = new String(123); console.log(str, typeof str); // String{'123'} 'object' const num = Number('123'); console.log(num, typeof num); // 123 'number' const num = new Number('123'); console.log(num, typeof num); // Number {123} 'object'끝
'IT > js' 카테고리의 다른 글
2021_12_17 Deep_Dive 11장 원시 값과 객체의 비교 (0) 2021.12.18 2021_12_17 Deep_Dive 10장 객체 정리 (0) 2021.12.17 2021_12_08 윤년계산 알고리즘 (0) 2021.12.08 2021_12_07 변수의 생명주기 (0) 2021.12.07 2021_12_04 node, npm 용어가 cmdlet... 에러 (0) 2021.12.04