본문 바로가기
Archive

new 연산자와 생성자 함수

by livemehere 2022. 8. 29.

태초의 자바스크립트는 클래스가 존재하지 않았다.

그래서 생성자함수와 prototype 으로 객체지향을 구현하곤 했었다.

그래서 유사한 객체를 만들기위해서 new 키워드와 생성자 함수를 함께 사용한다.

function User(name) {
  this.name = name;
  this.isAdmin = false;
}

const user = new User("kong");
console.log(user.name);
console.log(user.isAdmin);

 

생성자 함수라는것에는 기술적인 차이는 없다.

다만 두가지의 관례를 따를 뿐이다.

 

1. 함수이름은 대문자로 시작한다.

2. 반드시 'new' 연산자를 붙여 실행한다.

 

코딩에 마법은 없다고 했기에, 새로운 키워드 new 가 나왔다.

그럼 new 는 어떤 동작을해주는지 보면

 

1. 빈 객체를 만들어서 this에 할당한다.

2. 함수 본문을 실행하면서, this에 새로운 프로퍼티를 추가해서 this 를 수정한다.

3. this를 반환한다.

 

new 의 동작을 보면 왜 그냥 함수를 호출함으로써 객체를 만들지 않고 하는지 알 수 있다.

물론 위 3가지동작을 직접해줄 수 있지만, new 라는 키워드가 이런 용도로 나온 것임을 알 수 있다.

왜 이런식으로하는지는 클래스를 생각해보면 유추가되었다.

 

비슷한 객체를 만들기위해서 클래스라는 클을 만들고, 생성자함수에 초기값을 입력한다.

생성자함수는 이 과정을 하는 함수이다.

 

여기서 new 이런식으로 일반함수를 호출하는 것과는 다르게 동작하지만, 함수명이 대문자여야 한다는 것은 공동의 약속일 뿐이다.

new.target

function Check() {
  console.log(new.target);
}

Check(); //undefined
new Check();
/*
ƒ Check() {
  console.log(new.target);
}
*/

아주 생소한 문법인데, 알아둘 필요가 있다고 생각한다.

이 문법은 함수가 new 연산자를 통해서 호출되었는지를 판단할 수 있다

만약에 new 연산자로 호출되었다면, 함수 자체를 반환하고, 아니라면 undefined를 반환한다.

 

라이브러리를 분석하다보면 이를 활용해 new 연산자를 사용하지 않고도 내부적으로 객체를 만들어 반환하도록 사용하는 사례가 있다고한다.

function User(name) {
  if (!new.target) { // new 없이 호출해도
    return new User(name); // new를 붙여줍니다.
  }

  this.name = name;
}

let bora = User("보라"); // 'new User'를 쓴 것처럼 바꿔줍니다.
alert(bora.name); // 보라

위와같은 경우인데, 경험상 axios 라이브러리를 사용할때 new 연산자를 쓴적이없는것 같다.

아마 이런식으로 되있을 수도있다고 생각하는데, 직접 뜯어본 결과로는 static을 사용하는 것으로 기억하고있다.

나중에 한번 다시 살펴봐야겠다.

 

생성자 함수에서 return 구문이 있다면

new 연산자와 함께 함수를 호출하면 새로운 객체가 반환된다고 했는데, 이때는 return 구문이 따로 없다.

만약 return 구문이있다면 그게 객체가 아니라면 모두 무시된다.

function User(name) {
  this.name = name;
  this.isAdmin = false;
  return 1; // 무시하고 정상적으로 this 반환
}

function User(name) {
  this.name = name;
  this.isAdmin = false;
  return; // 무시하고 정상적으로 this 반환
}

function User(name) {
  this.name = name;
  this.isAdmin = false;
  return {}; // {} 반환
}

위와같이 동작한다.

 

또한 괄호를 생략해도 정상적으로 동작한다.

let user = new User; // <-- 괄호가 없음
// 아래 코드는 위 코드와 똑같이 동작합니다.
let user = new User();

 

생성자함수를 쓰는데에는 비슷한 객체를 만들어내는데에 있다.

즉 클래스와 목적이 동일하고, 기대효과도 동일하다.

Javascript에 내장되어있는 Date, Set 객체들을 이런 생성자 함수를 통해서 만들 수 있다.

그런데 지금은 class 문법이 존재하는 이상 굳이 객체를 만들어내는데 class가 아닌 생성자함수를 쓸이유는 없을거 같다.

 

반응형

'Archive' 카테고리의 다른 글

자바스크립트에서 숫자  (0) 2022.08.29
원시값의 메서드  (0) 2022.08.29
객체  (0) 2022.08.29
다시보는 babel 과 polyfill  (0) 2022.08.28
1년10개월 만에 다시보는 Javascript 기초  (0) 2022.08.28