new 연산자와 함께 Object 생성자 함수를 호출하면 빈 객체를 생성하여 반환한다.
const obj = new Object()
obj.hi = "hello"
console.log(obj.hi) // hello
String, Number,Boolean,Function,Array,Date,RegExp,promise 등의 빌트인 생성자 함수도 제공한다.
객체를 생성할때 객체 리터럴에 의해 생성하면 보기편하고 간단하다. 하지만 동일한 프로퍼티를 갖는 객체를 여러개 생성해야 할때는 비효율 적이다.
function Circle(radius){
// 생성자 함수 내부의 this는 생성할 인스턴스를 가리킨다
this.radius = radius
this.getDiameter = function(){
return 2 * this.radius
}
}
const circle1 = new Circle(5)
circle1 // Circle {radius: 5, getDiameter: ƒ} this로 객체의 키와 값이 만들어 졌다.
this??
this는 객체 자신의 프로퍼티나 메서드를 참조하기 위한 자기 참조 변수다.
일반함수로서 호출하면 전역 객체
메서드로서 호출하면 메서드를 호출한 객체
생성자 함수로서의 호출은 생성자 함수가 생성할 인스턴스
new 연산자와 함께 생성자 함수를 호출하면 암묵적으로 빈 객체를 생성한다 이 객체가 인스턴스다.
그리고 이 인스턴스는 this에 바인딩된다. 이 과정은 함수 코드의 런타임 이전에 실행된다.
바인딩??
식별자와 값을 연결하는 과정을 의미한다. 예로 변수선언은 식별자와 메모리 공간의 주소를 바인딩 하는거다.
함수 내 코드가 한줄씩 실행되어 this에 바인딩된 인스턴스를 초기화 한다. this에 바인딩 되어 있는 인스턴스에 프로퍼티나 메서드를 추가하고 인수로 전달받은 초기값을 할당하여 초기화 하거나 고정값을 할당한다.
생성자 함수 내부의 런타임이 끝나면 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
단. return 문에 명시한 객체가 있다면 그 객체가 반환된다, 원시값을 return 문에 명시했다면 그 원시 값은 무시된다.
function Circle(radius){
this.radius = radius
this.getDiameter = function(){
return 2 * this.radius
}
// 객체를 명시적으로 반환했다.
return {}
}
const circle1 = new Circle(5)
circle1 // {} this가 반환되지 못한다
function Circle(radius){
this.radius = radius
this.getDiameter = function(){
return 2 * this.radius
}
// 원시값를 명시적으로 반환했다.
return 100
}
const circle1 = new Circle(5)
circle1 // Circle {radius: 5, getDiameter: ƒ} 원시값을 명시적으로 반환했으나 무시됐다.
함수는 객체다. 하지만 일반 객체와는 다르게 호출 할 수 있다.
그래서 일반 객체가 갖고 있는 내부 슬롯과 내부 메서드, 함수 객체만을 위한 내부 슬롯인 [Environment][FormalParameters] 내부 메서드 [Call][Construct]를 가지고 있다.
함수를 일반 함수로써 호출하면 함수 객체의 내부 메서드[Call] 이 호출되고.
new 연산자로 생성자 함수로써 호출하면 [Construct] 가 호출된다.
내부 메서드 [Call]을 갖는 함수를 callable,
[Construct]를 갖는 함수 객체를 constructor,
[Construct]를 갖지 않는 함수 객체를 non-constructor 이라 부른다.
함수 객체는 내부 메서드 [Call]을 갖고 있으므로 호출 할 수 있다.
하지만 모든 함수 객체가 [Construct]를 가지고 있는건 아니다.
new 연산자와 함께 함수를 호출하면 생성자 함수로 동작한다. [Call]이 아닌[Construct]가 호출된다.
위에서 다루듯이 객체를 반환하지 않고 원시값을 반환하는 함수는 반환문이 무시되어 빈 객체를 생성한다.
객체를 반환하는 일반 함수는 함수가 생성한 객체를 반환한다.
생성자 함수를 일반적인 함수로서 호출하게 되면 함수 내부의 this가 전역 객체 window가 되니 주의한다.
생성자 함수는 첫 문자를 대문자로 기술한다.
생성자 함수가 new 연산자 없이 호출되면 this가 전역 객체가 된다고 했다. 이를 막기 위해 new.target을 지원한다.
function Circle(radius){
// 생성자 함수를 new연산자로 호출하는지 확인하는 조건문, 그렇지 않으면 재귀해서 new 연산자로써 호출 시킨다.
if(!new.target){
return new Circle(radius)
}
this.radius = radius
this.getDiameter = function(){
return 2 * this.radius
}
return 100
}
// 생성자 함수를 new 연산자 없이 호출했다
const circle1 = Circle(5)
circle1 // Circle {radius: 5, getDiameter: ƒ} 정상적으로 호출됐다.
스코프 세이프 생성자 패턴??
function Circle(radius){ // 생성자 함수를 new연산자로 호출하는지 확인하는 조건문, 그렇지 않으면 재귀해서 new 연산자로써 호출 시킨다. if(!(this instanceof Circle)){ return new Circle(radius) } this.radius = radius this.getDiameter = function(){ return 2 * this.radius } return 100 } // 생성자 함수를 new 연산자 없이 호출했다 const circle1 = Circle(5) circle1 // Circle {radius: 5, getDiameter: ƒ} 정상적으로 호출됐다.