객체는 리터럴로 생성하는것이 일반적이다. 근데 단점은 하나밖에 생성을 못한다는 것.
객체 생성자 함수의 장점은 프로퍼티 구조가 동일한 객체를 많이 만들때, 간편하게 생성할수있다는것이다.
마치 클래스처럼 객체(인스턴스)를 생성할수있다. new 연산자와 함께 호출하면 생성자 함수로 동작한다.
최근 트렌드가 new 연산자는 안쓰는거지만 레거시 코드를 마주할 수 있으니.... 알아보도록 하자~
function Square(n){
this.n = n;
this.getSquare = function(){
return n*n;
}
}
const sq1 = new Square(5); // Square {n: 5, getSquare: ƒ}
const sq2 = new Square(10); // Square {n: 10, getSquare: ƒ}
sq1.getSquare() // 25
this는 객체 자신의 프로퍼티, 메서드를 참조하기 위한 자기참조 변수이다.
this는 호출 방식에 따라 동적으로 결정된다.
생성자 함수가 생성한 인스턴스는 this에 바인딩 된다.
생성자 함수의 인스턴스 생성 과정
1. 인스턴스 생성
2. this 바인딩
3. 인스턴스 초기화(프로퍼티 추가 및 할당)
4. 인스턴스 반환
반환을 명시하지않으면 암묵적으로 this가 반환되고,
반환을 명시할때 원시값을 반환하면 무시하고 this를 반환한다.
이는 함수의 기본동작을 훼손하므로 생성자 함수 내에서 return문은 생략해야한다.
함수는 객체다 !
근데 일반객체랑은 다르다. 일반 객체는 호출할수 없지만, 함수는 호출할수있다.
함수객체는 [[Environment]], [[FormalParameters]] 등의 내부슬롯과, [[Call]],[[Construct]]같은 내부 메서드를 추가로 가진다.
function funcIsObject(){}
funcIsObject.prop = 10;
funcIsObject.method = function(){
console.log('this.prop::',this.prop);
}
funcIsObject.method() // this.prop:: 10
function funcIsObject(){}
funcIsObject(); // [[Call]] 호출
new funcIsObject(); // [[Construct]] 호출
함수가 일반함수로 호출되면 [[Call]]이 호출되고, 생성자 함수로서 호출되면 [[Construct]]가 호출된다.
일반함수로 정의된 함수만 constructor이다.
function test(){} // 함수 선언문
const innerTest = function(){}; // 함수 표현식
const testTwo = {
v1: function(){} // 일반함수. 메서드로 인정안함
}
new test(); // test {}
new innerTest(); // innerTest {}
new testTwo.v1(); // v1 {}
// 일반함수로 정의된 함수만 constructor
const check = () => {};
new check(); // check is not a constructor
const testObj = {
x(){} // 일반함수 아니고 메서드로 인정된다. ECMAScript 사양에서의 메서드는, ES6의 축약표현만 해당.
}
new testObj.x() // testObj.x is not a constructor
일반함수와 생성자 함수에 특별한 형식적 차이는 없다.
파스칼 케이스(첫글자 대문자)로 명명하여 일반함수와 구분을 한다.
new 연산자와 함께 호출하면 해당 함수는 생성자로 동작하고, [[Call]]이 아닌 [[Construct]]가 호출된다.
new.target
new 연산자를 사용해 생성자 함수로서 호출되면, 함수 내부의 new.target은 함수 자기자신을 가리킨다.
일반함수로 호출된 내부의 new.target은 undefiend이다.
빌트인 생성자 함수
대부분의 빌트인 생성자 함수는(Object, String, Number, Boolean, Function, Array, Date, RegExp, Promise)는 new 연산자와 함께 호출되었는지 확인후 적절한 값을 반환한다.
const str1 = new String(123); // String {'123'} 객체리턴
const str2 = String(123); // '123'
const num1 = new Number('123'); // Number {123} 객체리턴
const num2 = Number('123'); // 123
const bool1 = new Boolean(1) // Boolean{true} 객체리턴
const bool2 = Boolean(1) // true
const obj1 = new Object(); // {}
const obj2 = Object(); // {}
const set1 = new Set([1,2,1,2]) // Set(2) {1,2}
const set2 = Set([1,2,1,2]) // Type Error : Constructor Set requires 'new'
const sym1 = new Symbol('123') // Type Error : Symbol is not a constructor
const sym2 = Symbol('123') // Symbol(123)
참고로 Set은 new 연산자를 필요로 하고, Symbol은 생성자로 사용할 수 없다.
'[STUDY] 스터디 > Deep Dive JS' 카테고리의 다른 글
js this (0) | 2022.12.17 |
---|---|
js strict mode / ESlint (0) | 2022.12.06 |
js 프로퍼티 어트리뷰트 / js 프로토타입 (0) | 2022.11.28 |
스코프와 전역변수의 문제점 (0) | 2022.11.25 |
js 함수 리터럴 / 화살표함수 / 콜백함수 / 고차함수 정의 (0) | 2022.11.24 |