모던 자바스크립트 Deep Dive 17장-생성자 함수에 의한 객체 생성

Object 생성자 함수

const person = new Ojbect(); //빈 객체 생성 {}

생성자 함수 : new연산자와 함께 호출하여 객체(인스턴스)를 생성하는 함수
Date,String,Number,Boolean,Array...

생성자 함수

객체 리터럴에 의한 객체 생성 방식의 문제점

동일한 프로퍼티를 갖는 객체를 여러개 선언할 때 일일히 다 코드 작성해야함

const person1 = {
	name : 'aj',
    hi(){
		console.log(`hi i'm ${name}`);
    };

const person2 = {
	name : 'sam',
    hi(){
		console.log(`hi i'm ${name}`);
    };

생성자 함수에 의한 객체 생성 방식의 장점

객체를 생성하기 위한 템플릿처럼 프로퍼티 구조가 동일한 객체 여러개를 간편하게 생성

function Person(name){
	this.name = name;
    this.hi = function(){
    	console.log(`hi i'm ${name}`);
    };
}

const person1 = new Person('aj');
const person2 = new Person('sam');

this

  • 일반 함수에서 호출 시 : this는 전역 객체를 가르킴
  • 메서드에서 호출 시 : 메서드를 호출한 그 객체를 가르킴
  • 생성자 함수에서 호출시 : 앞으로 생성될 인스턴스를 가르킴

생성자 함수는 new연산자 없이 호출하면 일반 함수로 동작

생성자 함수의 인스턴스 생성 과정

new연산자와 함께 생성자 함수를 호출하면 자바스크립트 엔진은 암묵적으로 인스턴스를 생성,초기화하여 반환한다

인스턴스 생성과 this 바인딩

암묵적으로 빈 객체(인스턴스)를 생성하고 this와 바인딩
this는 생성된 인스턴스를 가르킴
함수의 모든 코드가 한 줄씩 실행되는 런타임 이전에 먼저 발생함

인스턴스 초기화

생성자 함수의 코드대로 this가 가르키는 인스턴스를 초기화한다
= 빈 객체에 프로퍼티와 메서드를 추가

인스턴스 반환

생성자 함수 내부의 모든 처리가 끝난 인스턴스가 바인딩된 this를 암묵적으로 반환
return을 생략해서 암묵적으로 this가 반환되게 냅둔다
return {특정객체} 를 해주면 this반환 안하고 특정객체 반환
return 원시값 은 무시되고 this를 반환

내부 메서드 [[Call]]과 [[Construct]]

함수는 객체이기 때문에 프로퍼티와 메서드를 갖을 수 있다
함수 객체도 일반 객체가 갖고 이는 내부 슬롯과 내부 메서드를 모두 갖고 있다
하지만 함수는 호출이 가능하다
함수 객체만을 위한 내부 슬롯과 내부 메서드 [[Call]],[[Construct]]를 갖고 있다

함수가 일반 함수로 호출되면 [[Call]]이 호출, new연산자와 함께 생성자 함수로 호출되면 [[Construct]]가 호출

함수객체는 반드시 [[Call]]을 갖는다 callable
[[Construct]]는 갖을수도, 안갖을수도

construct와 non-construct의 구분

화살표 함수와 메서드 축약 표현으로 선언된 함수만 non-construct
함수 선언문과 함수 표현식은 construct

const hi = () => {
	console.log('hi');
};
new hi() // [[construct]]가 없으므로 에러

const obj = {
	hi(){
    console.log('hi');
    }
};
new obj.hi(); // [[construct]]가 없으므로 에러

new연산자

일반 함수와 생성자 함수의 형식적 차이는 없다
단지 new연산자와 함께 함수를 호출하면 생성자 함수로 동작한다
고로 작명할 때 파스칼 케이스로 작성

생성자 함수를 new없이 호출하면 일반 함수로 동작
일반 함수로 동작하면 this는 전역객체(window,global)을 가르킴

function Person(name){
	this.name = name;
}

const person1 = Person('aj');
console.log(person1); // undefined
console.log(name) // 전역객체에 name프로퍼티의 값인 aj 출력

new.target

IE 지원 안함, ES6 지원
new연산자와 함께 생성자 함수로 호출된 함수내부에서 new.target은 함수 자신을 가르킴
일반 함수로 호출된 함수 내부에서 new.target은 undefined

new 빼먹었을 때에도 생성자 함수처럼 동작하게 만들기

function Person(name){
	if (!new.target){
		return new Person(name);
    }
    this.name = name;
}


// 스코프 세이프 생성자 패턴으로 똑같이 동작하게 
// 생성자 함수가 new연산자와 함께 호출되면 바로 빈 객체를 생성하고
// this와 바인딩이 되고 this는 Person과 프로토타입에 의해 연결됨
// 일반 함수로 호출이 됐다면 this는 window객체를 가르킬꺼임
function Person(name){
	if (!(this instanceOf Person)){
		return new Person(name);
    }
    this.name = name;
}

Object,Function 생성자 함수는 new없이 써도 똑같이 동작
String,Number,Boolean은 new없이 쓰면 원시값 자체를 데이터 타입만 적용해서 반환

좋은 웹페이지 즐겨찾기