new 연산자와 생성자 함수
객체 리터럴 {...}
을 사용하면 객체를 쉽게 만들 수 있습니다. 그런데 개발을 하다 보면 유사한 객체를 여러 개 만들어야 할 때가 생기곤 합니다. 복수의 사용자, 메뉴 내 다양한 아이템을 객체로 표현하려고 하는 경우가 그렇죠.
'new'
연산자와 생성자 함수를 사용하면 유사한 객체 여러 개를 쉽게 만들 수 있습니다.
생성자 함수(constructor function)와 일반 함수에 기술적인 차이는 없습니다. 다만 생성자 함수는 아래 두 관례를 따릅니다.
함수 이름의 첫 글자는 대문자로 시작합니다.
반드시
'new'
연산자를 붙여 실행합니다.
예시:
new User(...)
를 써서 함수를 실행하면 아래와 같은 알고리즘이 동작합니다.
빈 객체를 만들어
this
에 할당합니다.함수 본문을 실행합니다.
this
에 새로운 프로퍼티를 추가해this
를 수정합니다.this
를 반환합니다.
예시를 이용해 new User(...)
가 실행되면 무슨 일이 일어나는지 살펴 보도록 하겠습니다.
이제 let user = new User("보라")
는 아래 코드를 입력한 것과 동일하게 동작합니다.
new User("보라")
이외에도 new User("호진")
, new User("지민")
등을 이용하면 손쉽게 사용자 객체를 만들 수 있습니다. 객체 리터럴 문법으로 일일이 객체를 만드는 방법보다 훨씬 간단하고 읽기 쉽게 객체를 만들 수 있게 되었죠.
생성자의 의의는 바로 여기에 있습니다. 재사용할 수 있는 객체 생성 코드를 구현하는 것이죠.
잠깐! 모든 함수는 생성자 함수가 될 수 있다는 점을 잊지 마시기 바랍니다. new
를 붙여 실행한다면 어떤 함수라도 위에 언급된 알고리즘이 실행됩니다. 이름의 '첫 글자가 대문자’인 함수는 new
를 붙여 실행해야 한다는 점도 잊지 마세요. 공동의 약속이니까요.
new function() { … }
재사용할 필요가 없는 복잡한 객체를 만들어야 한다고 해봅시다. 많은 양의 코드가 필요할 겁니다. 이럴 땐 아래와 같이 코드를 익명 생성자 함수로 감싸주는 방식을 사용할 수 있습니다.
위 생성자 함수는 익명 함수이기 때문에 어디에도 저장되지 않습니다. 처음 만들 때부터 단 한 번만 호출할 목적으로 만들었기 때문에 재사용이 불가능합니다. 이렇게 익명 생성자 함수를 이용하면 재사용은 막으면서 코드를 캡슐화 할 수 있습니다.
심화 학습
이 절에서 소개할 문법은 자주 쓰이지 않습니다. 자바스크립트의 모든 문법을 학습하고 싶지 않다면 넘어가셔도 좋습니다.
new.target
프로퍼티를 사용하면 함수가 new
와 함께 호출되었는지 아닌지를 알 수 있습니다.
일반적인 방법으로 함수를 호출했다면 new.target
은 undefined를 반환합니다. 반면 new
와 함께 호출한 경우엔 new.target
은 함수 자체를 반환해줍니다.
함수 본문에서 new.target
을 사용하면 해당 함수가 new
와 함께 호출되었는지(in constructor mode) 아닌지(in regular mode)를 확인할 수 있습니다.
이를 활용해 일반적인 방법으로 함수를 호출해도 new
를 붙여 호출한 것과 같이 동작하도록 만들어보겠습니다.
라이브러리를 분석하다 보면 위와 같은 방식이 쓰인 걸 발견할 때가 있을 겁니다. 이런 방식을 사용하면 new
를 붙여 함수를 호출하든 아니든 코드가 동일하게 동작하기 때문에, 좀 더 유연하게 코드를 작성할 수 있습니다.
그런데 이 방법을 믿고 객체를 만드는 경우에도 new
를 생략하면 코드가 정확히 무슨 일을 하는지 알기 어렵습니다. new
가 붙어있으면 새로운 객체를 만든다는 걸 누구나 알 수 있기 때문에 new
를 생략해서 객체를 만드는것은 정말 필요한 경우에만 사용하시고 남발하지 않으시길 바랍니다.
생성자 함수엔 보통 return
문이 없습니다. 반환해야 할 것들은 모두 this
에 저장되고, this
는 자동으로 반환되기 때문에 반환문을 명시적으로 써 줄 필요가 없습니다.
그런데 만약 return
문이 있다면 어떤 일이 벌어질까요? 아래와 같은 간단한 규칙이 적용됩니다.
객체를
return
한다면this
대신 객체가 반환됩니다.원시형을
return
한다면return
문이 무시됩니다.
return
뒤에 객체가 오면 생성자 함수는 해당 객체를 반환해주고, 이 외의 경우는 this
가 반환되죠.
아래 예시에선 첫 번째 규칙이 적용돼 return
은 this
를 무시하고 객체를 반환합니다.
아무것도 return
하지 않는 예시를 살펴봅시다. 원시형을 반환하는 경우와 마찬가지로 두 번째 규칙이 적용됩니다.
return
문이 있는 생성자 함수는 거의 없습니다. 여기선 튜토리얼의 완성도를 위해 특이 케이스를 소개해보았습니다.
괄호 생략하기
인수가 없는 생성자 함수는 괄호를 생략해 호출할 수 있습니다.
명세서엔 괄호를 생략해도 된다고 정의되어 있지만, '좋은 스타일’은 아닙니다.
생성자 함수를 사용하면 매개변수를 이용해 객체 내부를 자유롭게 구성할 수 있습니다. 엄청난 유연성이 확보되죠.
지금까진 this
에 프로퍼티를 더해주는 예시만 살펴봤는데, 메서드를 더해주는 것도 가능합니다.
아래 예시에서 new User(name)
는 프로퍼티 name
과 메서드 sayHi
를 가진 객체를 만들어줍니다.
class 문법을 사용하면 생성자 함수를 사용하는 것과 마찬가지로 복잡한 객체를 만들 수 있습니다. class에 대해선 추후 학습하도록 하겠습니다.
생성자 함수(짧게 줄여서 생성자)는 일반 함수입니다. 다만, 일반 함수와 구분하기 위해 함수 이름 첫 글자를 대문자로 씁니다.
생성자 함수는 반드시
new
연산자와 함께 호출해야 합니다.new
와 함께 호출하면 내부에서this
가 암시적으로 만들어지고, 마지막엔this
가 반환됩니다.
생성자 함수는 유사한 객체를 여러 개 만들 때 유용합니다.
자바스크립트는 언어 차원에서 다양한 생성자 함수를 제공합니다. 날짜를 나타내는 데 쓰이는 Date
, 집합(set)을 나타내는 데 쓰이는 Set
등의 내장 객체는 이런 생성자 함수를 이용해 만들 수 있습니다. 자세한 내용은 다시 살펴보도록 하겠습니다.
아직 배울 게 많습니다!
이번 챕터에서 다룬 것은 객체와 생성자에 대한 기본에 불과합니다. 이어지는 챕터에서 다룰 자료형과 함수를 이해하는 데 꼭 필요한 내용이죠.
객체에 대한 학습은 아직 끝나지 않았습니다. 자료형과 함수를 학습한 이후에 다시 객체로 돌아와 프로토타입과 프로토타입 상속, 클래스등을 다루도록 하겠습니다.
Last updated