[JS] new 연산자와 생성자 함수

MJ·2022년 9월 6일
0

Java Script

목록 보기
34/57
post-thumbnail

객체 리터럴

  • 객체를 생성할 때 리터럴 {...} 방식을 사용하면 간편하게 객체를 생성할 수 있습니다.

  • 하지만 객체를 만들다보면 유사한 객체를 여러 개를 생성할 때가 생깁니다. 복수의
    사용자와 메뉴의 다양한 기능들을 객체로 표현하려고 하는 경우와 같이 말이죠.

  • new 연산자를 사용해서 객체를 생성하면, 여러 곳에 유사한 객체를 할당할 수 있습니다.



생성자 함수

  • 첫 글자를 대문자로 하고 함수명 앞에 new연산자를 붙이면 생성자 함수가 된다.
    2가지 주의사항이 있습니다.

※ 주의사항
1. 함수의 이름의 첫 글자는 대문자로 시작해야 한다.
2. 함수를 호출할 때 new 연산자를 붙여야 한다.

/* 생성자 함수 생성 */

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

let user = new User('보라'); 

alert(user.name);		// 보라
alert(user.isAdmin);	// false


/* new User() 함수를 호출하는 과정 */
1. User 함수 호출 인수 값으로 '보라' 전달 
2. User 함수에서 { } 빈 객체를 생성하고, this할당 ( this { } )
3. 함수 본문을 수행한다. 
	this.name = name; ( name == '보라' )
	this.isAdmin = false;

4. 마지막으로 this {} 객체 참조값을 반환합니다.
5. user 변수에서 this {} 객체에 접근할 수 있다.


❗ User가 일반 함수였다면, this로 프로퍼티를 생성하거나 접근할 수 없습니다.

/* new 생성자 함수 동작 원리 */

let user = new User('보라');

function User(name) {
	// this = { } 빈 객체 생성
  
  this.name = name;	
  this.isAdmin = false;
  
	// 실행흐름이 끝나면 this가 반환된다. ( return this; )
}


/* 
동작 원리
	
1. new 연산자로 User 함수를 호출 합니다.
2. User 함수는 new 연산자로 호출했기에 생성자 함수가 되므로, 빈 객체를 함수 내부에 생성
3. 객체가 생성되었으므로 this 연산자로 객체에 접근할 수 있게 됩니다.
* 함수 내부에서 his = { } 빈 객체가 생성되었다고 생각 *

4. 빈 객체에 프로퍼티를 할당한다.
this = { name : name, isAdmin : false }

5. 함수의 실행흐름이 끝나면 return을 사용하지 않아도, 알아서 반환한다.
*/

/* 생성자 함수를 통해서 유사한 객체 여럿 생성 하기 */

function User(name,boolean) {
  this.name = name;
  this.isAdmin = (boolean === undefined) ? false : boolean;
}

let user = new User("보라");
let user2 = new User('철수',true);
let user3 = new User('유리',true);

console.log(user.name); 	// 보라
console.log(user.isAdmin);	// false
console.log(user2.name);	// 철수
console.log(user2.isAdmin); // true
console.log(user3.name);	// 철수
console.log(user3.isAdmin);	// true


/* 
생성자 함수 (User) 하나로, 여러 개의 객체를 만들어서 여러 변수에 반환할 수 있습니다.
*/

🔔 모든 함수는 생성자 함수가 될 수 있다.

앞서 설명한 2가지만 지킨다면 어떤 함수던지 생성자 함수로 생성할 수 있습니다.
그리고 생성자 함수의 가장 큰 장점은, 재사용할 수 있는 객체를 만들 수 있다는 것


1.1 생성자 함수를 익명함수로 만들기

  • 생성자 함수를 재사용할 이유가 없는 경우에는 익명함수로 생성하는게 효율적입니다.
    함수를 호출한 곳 이외에는 호출할 수 없으므로 코드를 캡슐화 할 수 있습니다.
let user = new function() {
  this.name = "John";
  this.isAdmin = false;
};

1.1 new.target과 생성자 함수

  • new.target 프로퍼티를 사용하면 함수가 일반 함수인지 생성자 함수인지 구분할 수 있다.

  • 일반 함수를 호출하면 undefined를 반환하고, 생성자 함수를 호출하면 함수 자체를 반환함.

function User() {
 alert(new.target); 
}

User();		// Undefined, 일반 함수
new User();	// function User() {....}, 함수 자체가 호출 된다.

/* 
함수 본문에서 `new.target`을 사용하면 해당 함수가 `new`와 함께 호출되었는지 아닌지 유무를
확인할 수 있습니다. 

이 방법으로 일반 함수를 호출해도 `new`를 붙여서 호출한 것과 같이 동작 하도록 만들 수도 있습니다.
*/

/* 호출 함수가 일반 함수라면 생성자 함수로 반환 */

function User(name) {
  if( !new.target ) {       // User(name) 함수가 생성자 함수가 아니라면
    return new User(name);  // User(name) 함수를 생성자 함수로 만들고 반환한다.
  }
  // 생성자 함수가 되어 this 객체가 생성되고 프로퍼티를 만들 수 있다.

  this.name = name;       // this{ name: name }; 구문같이 동작한다고 이해합시다. 
}


let bora = User("보라"); 
 
console.log(bora.name); // 출력 : 보라, bora. 으로 접근할 수 있는 이유는 생성자 함수 this 객체의
						// 참조 값이 할당 되었기 때문이다.


/* 
이런 방식으로 생성자 함수를 정의하는 것은 거의 없다.

`new` 연산자를 사용하지 않아도 함수 내부에서 정의해주니 조금 더 유연하게 생성자 함수를
사용할 수 있습니다.

다만 이 방법보다는 생성자 함수라면 `new` 연산자를 붙여서 생성하는 것을 권장합니다.
*/

1.3 생성자와 retrun문

  • 생성자 함수에서는 return 지시자를 사용하지 않습니다.

  • 반환해야 할 것들은 this { } 객체에 저장되고, this는 자동으로 반환하기 때문에
    return이 불필요 합니다.

생성자 함수에서 return문을 사용하면 아래 같은 규칙이 적용 됩니다.

1. 객체를 return 하면 this 대신에 객체가 반환됩니다.
2. 원시값을 return 하면 return 문을 무시합니다.

return 뒤에 객체가 오면 생성자 함수는 객체를 반환하고, 이외의 경우에는 this
반환 합니다.


/* 객체를 return 하기 */

function User() {
  this.name = '철수';	
  
  return {			// 객체에 return 지시자가 붙으면, this를 무시하고 객체를 반환합니다.
	name: '영희'
  };
}

alert ( new User().name );	// '영희' , this { } 객체는 참조하지 않는다.

/* this 객체가 원시값을 반환 */

function User() {
  this.name = '철수';	// '철수'는 원시자료형입니다. (문자열)
  
  return;			// return 지시자뒤에 객체가 없기에 this를 반환한다.
}

alert ( new User().name ); // '철수'


/* 
만약 return 뒤에 객체가 붙어 있다면, this.name에 원시값이 있더라도 return { } 객체가 반환됩니다.
*/

🔔 괄호 생략

생성자 함수에 인수가 없다면 () 괄호를 생략해서 호출할 수 있습니다.
다만 이는 가독성이 좋지 않으므로 사용하지 않기로 합시다.

⚠️ 좋지 않은 코드
let user = new User; 
/
✅ 좋은 코드
let user = new User();

1.4 생성자 함수 내부의 메서드

  • 생성자 함수는 생성될 때 this { } 객체를 기본적으로 생성합니다.

  • 이외에도 메서드 자체를 추가로 생성할 수 있습니다.

/* 메서드 생성 */

function User(name) {
 this.name = name;	// this.name: 철수 
  
 this.sayHi = function() {		// 메서드 생성
  alert('내 이름은 ' + this.name + '야 잘부탁해 !'); 
 }
}

let chulsu = new User('철수');	
chulsu.sayHi();	// 메서드 호출, 내 이름은 철수야 잘부탁해 !



정리

모든 함수는 생성자 함수가 될 수 있습니다. 함수를 생성할 때 첫 글자를 대문자로 하고, 함수를
호출할 때는 new 연산자를 사용하면 됩니다.


생성자 함수를 호출할 때는 new 연산자가 필수입니다. new를 사용해서 생성자를 호출하면
암시적으로 this가 만들어지고, 마지막에 this를 반환합니다.


이미 생성된 일반 함수를 생성자 함수로 변경하려면, new.target 을 사용해서 일반 함수를
생성자 함수로 변경할 수 있습니다. 추천하는 방법은 아닙니다.

이 기능은, 함수가 일반함수인지 생성자 함수인지 유무도 파악해줍니다.
일반 함수 : undefined
생성자 함수 : 함수 자체의 코드를 반환

profile
프론트엔드 개발자가 되기 위한 학습 과정을 정리하는 블로그

0개의 댓글