04. 생성자 함수
📌 4-1 생성자 함수란?
ES6 문법 이전에 함수를 클래스형태로 사용할 수 있는 함수이다.
💡 new 연산자를 사용하여 클래스처럼 객체를 생성한다. (인스턴스 생성)
💡 this를 사용하여 외부에서 접근할 수 있도록 한다.
💡 var, let, const 사용하여 변수를 생성하면 생성자함수 안에서만 연산이 된다.
💡 Class Naming 처럼 파스칼 표기법을 사용하여 구별할 수 있도록 한다.
📌 4-2 생성자 함수를 사용이유
인스턴스를 생성하는 클래스처럼 객체를 효율적으로 생성할 수 있다.
// 좌항 피연산자가 10 우항 피연산자가 2 더하기 연산을 수행하는 add()를 포함하는 Obj생성 const sum1 = { num1 : 10, num2 : 2, add() { return this.num1 + this.num2; } } // 좌항 피연산자가 10 우항 피연산자가 10 더하기 연산을 수행하는 add()를 포함하는 Obj생성 const sum2 = { num1 : 10, num2 : 10, add() { return this.num1 + this.num2; } } console.log(sum1.add()); // 12 출력 console.log(sum2.add()); // 20 출력
객체리터럴로 생성하면 다른 결과값을 얻기 위해서 계속 동일한 프로퍼티를 갖는 객체를 여러개 생성한다.
// 생성자 함수를 이용한 Obj 생성 function Sum(num1, num2) { this.num1 = num1; this.num2 = num2; this.add = function() { return this.num1 + this.num2; } } // 인스턴스 sum1 생성 const sum1 = new Sum(10, 2); // 인스턴스 sum2 생성 const sum2 = new Sum(10, 10); console.log(sum1.add()); // 12 출력 console.log(sum2.add()); // 20 출력
이와 같이 효율적으로 다른 결과값의 객체를 생성할 수 있다.
📌 4-3 생성자 함수의 외부접근 내부접근
-
생성자 함수를 이용하면 외부접근이 가능한 변수 this와 외부접근이 불가능한 변수를 만들수 있다.
-
var를 사용하여도 함수 레벨 스코프이기 때문에 외부로 전역변수화가 일어나진 않지만 내부에서는 일어나기 때문에 const와 let을 사용한다.
function Sum(num1, num2) { this.num1 = num1; this.num2 = num2; const numPrivate = 2; this.add = function() { return this.num1 + this.num2 - numPrivate; } } // 인스턴스 생성 const sum1 = new Sum(10, 2); // 외부에서 접근 가능 console.log(sum1.num1); // 10 출력 console.log(sum1.numPrivate); // undefined 출력 console.log(sum1.add()); // 10 출력
이와 같이 내부에서만 사용가능한 변수와 외부에서 접근 가능한 변수를 생성한다.
📌 4-4 생성자 함수의 생성조건
생성자 함수로 인스턴스를 생성할려면 일반 함수로 정의된 함수만 가능하다.
// 함수 선언문 function Sum(num1, num2) { this.num1 = num1; this.num2 = num2; this.add = () => { return this.num1 + this.num2; } } // 함수 표현식 const FunSum = function (num1, num2) { this.num1 = num1; this.num2 = num2; this.add = () => { return this.num1 + this.num2; } } // 화살표 함수 정의식 const ArrowSum = (num1, num2) => { this.num1 = num1; this.num2 = num2; this.add = () => { return this.num1 + this.num2; } } // 각각 인스턴스 생성 const sum1 = new Sum(10, 2); const sum2 = new FunSum(10, 2); const sum3 = new ArrowSum(10, 2); console.log(sum1.add()); // 12 출력 console.log(sum2.add()); // 12 출력 console.log(sum3.add()); // 오류 출력 👉 'ArrowSum is not a constructor' (오류)
이유는 함수를 생성할 때 가지고 있는 내부 메서드에 의한 현상이다.
1. 일반 함수로 호출을 하면 내부메서드 [[Call]]이 호출된다.
2. new 연산자와 생성자 함수가 호출이 되면 내부 메서드 [[Construct]]가 호출되기 때문이다.💡 그러므로 생성자 함수 안에서 사용한 화살표 함수는 메서드로는 사용이 가능하지만 생성자 함수로는 사용이 불가능하다.
📌 4-5 Callable, Constructor
함수 표현식의 prototype과 화살표 함수 정의식의 prototype을 확인해보면 생성자 함수로 사용할 수 없는 이유를 확인이 가능하다.
const generalFunction = function () {} // 함수 표현식 const arrowFunction = () => {} // ES6 화살표 함수 정의식 console.log(generalFunction.prototype); // 이미지 참고 console.log(arrowFunction.prototype); // undefined 출력
👀 generalFunction의 프로토타입에 constructor의 메서드로 인해 생성자함수로 호출이 가능하다.
📌 4-6 생성자 함수의 this
this가 가르키는 객체는 크게 3가지로 바인딩 된다.
1. 함수호출 this -> 전역 객체
2. 객체 메서드로서 호출 -> 메서드 호출 객체
3. 생성자 함수로서 호출 -> 생성한 인스턴스 객체// 함수 생성 function generalFunction(num1, num2) { console.log(this); return num1 + num2; } // 객체 생성 const object = { num1 : 10, num2 : 10, add : function() { console.log(this); return this.num1 + this.num2; } } // 생성자 함수 생성 function ConstructorFunction(num1, num2) { this.num1 = num1; this.num2 = num2; this.add = () => { console.log(this); return this.num1 + this.num2; } } // sum1에 함수호출값 저장 const sum1 = generalFunction(10, 10); // sum2에 오브젝트 저장 const sum2 = object; // sum3, sum4에 인스턴스 생성 const sum3 = new ConstructorFunction(10, 10); const sum4 = new ConstructorFunction(10, 10); // this가 인스턴스를 가르키는지 확인하기 위해서 sum5에 obj 저장 const sum5 = object; // obj안에 있는 num1에 20 재할당 sum2.num1 = 20; // 인스턴스 객체 sum4에 this.num1 = 20 재할당 sum4.num1 = 20; console.log(sum1); // 20 출력 전역객체 this console.log(sum2.add()); // 30 출력 객체 Obj 가르키는 this 출력 console.log(sum3.add()); // 20 출력 새롭게 생성된 인스턴스를 가르키는 this 출력 console.log(sum4.add()); // 30 출력 새롭게 정의된 인스턴스를 가르키는 this 출력 console.log(sum5.add()); // 30 출력 객체 obj 가르키는 this 출력
📃 4-6 설명
- 객체와 배열은 원시값이 아니므로 변수에 값이 저장되는 것이 아닌 배열과 객체를 가리키는 주소값이 저장된다고 생각하면 이해가 빠르다.
- sum2.num1를 20으로 바꾸면 sum5도 obj 주소값이 저장되어 있으므로 sum5의 출력값도 obj의 값이 변했으므로 바뀌게 되는것이다.
- sum4.num1를 20으로 바꾸더라도 인스턴스는 새롭게 생긴 객체이기 때문에 sum3과 sum4는 주소값을 다르게 가지는 객체 2개가 생성이 된다. 그래서 결과값도 바뀌지 않는다.
📌 4-7 생성자 함수의 결과값 반환
생성자 함수의 결과값은 this 객체이다.
// 생성자 함수 생성 function ConstructorFunction(num1, num2) { // 1. 빈 객체를 생성하고 this를 바인딩한다. (빈 객체 생성) // 2. this에 바인딩 값을 초기화 하고 생성자 함수가 받은 초기값을 할당한다. this.num1 = num1; this.num2 = num2; this.add = () => { return this.num1 + this.num2; } /* 3. 생성자 함수의 실행문이 종료되면 암묵적으로 생성자 함수가 받은 초기값으로 바인딩된 this를 반환한다. */ // 명시적으로 return 값을 원시값으로 지정한다. return 0; } const sum = new ConstructorFunction(10, 10); console.log(sum);
// 생성자 함수 생성 function ConstructorFunction(num1, num2) { this.num1 = num1; this.num2 = num2; this.add = () => { return this.num1 + this.num2; } // 명시적으로 return 값을 객체로 지정한다. (함수도 객체이다.) return {}; // function () {} 바꾸면 함수가 출력된다. } const sum = new ConstructorFunction(10, 10); console.log(sum);
function ConstructorFunction(num1, num2) { this.num1 = num1; this.num2 = num2; this.add = () => { return this.num1 + this.num2; } // 명시적으로 return 값을 this로 지정 return this; } const sum = new ConstructorFunction(10, 10); console.log(sum);
💡 생성자 함수는 생성된 인스턴스의 this 객체를 return 한다.
📌 4-8 생성자 함수 메서드를 prototype으로 생성하기
졸업작품 프로젝트를 하다가 본 템플릿 모듈에서는 생성자 함수 메서드를 prototype으로 생성하고 있었다. 이것도 깔끔해보여서 졸업작품 프로젝트에서는 모듈을 만들 때 이렇게 사용했었다.
function ConstructorFunction(num1, num2) { this.num1 = num1; this.num2 = num2; } ConstructorFunction.prototype.add = function() { return this.num1 + this.num2; } const sum = new ConstructorFunction(10, 10); console.log(sum.add()); // 20 출력
👉 bind(), call(), apply(), ES6 new.target 등등 생성자 함수의 개념들이 아직 많은것 같다... 너무 길어질꺼 같아서 다음에 다시 정리해 봐야겠다.
Author And Source
이 문제에 관하여(04. 생성자 함수), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@yhj96/04.-생성자-함수저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)