[Effective JavaScript] 생성자가 new와 관계없이 동작하게 만들자

김범식·2023년 7월 17일
0

Effective JavaScript

목록 보기
30/33
post-thumbnail

생성자가 new와 관계 없이 동작하게 만들자




new 연산자로 객체 생성

User 함수와 같은 생성자를 만들 때, 호출자는 반듣시 new 연산자를 통해 호출해야 한다.

function User(name, age){
	this.name = name
	this.age = age
}

new 키워드를 깜빡했다면 어떻게 될까?

var u = User("이순신",45);
u; // undefined
this.name ;// 이순신
this.age ;// 45

함수의 수신자 객체는 전역 객체가 되버린다. 함수가 undefined를 반환할 뿐만 아니라 전역변수에 name과 age가 이미 존재한다면 수정하게 된다.

“use strict” 사용

function User(name, age){
	"use strict"
	this.name = name
	this.age = age
}

var u = User("이순신",45);   //오류 : this가 정의되지 않음

“use strict” 를 사용하면 잘못된 호출로 인한 오류가 발생한다. 이처럼 스트릭트 모드를 사용하면 호출자는 버그를 빨리 발견하고 고칠 수 있다.

new 키워드에 상관없이 객체 만들기

function User(name, age){
	if(!this instanceof User){
		return new User(name,age)
	}
	this.name = name
	this.age = age
}

new 연산자 없이 생성자 함수를 실행한다면 this전역객체가 되기 때문에 User의 인스턴스가 아니게 된다. 그점을 이용하여 다음과 같은 코드를 작성하면 new 키워드 없이 생성자를 사용할 수 있다.

var x = User("이순신", 45);
var y = new User("강감찬", 42);

x instanceof User //true
y instanceof User //true

이 패턴의 단점은 추가적인 함수 호출이 필요하기 때문에 약간의 비용이 더 든다는 점이다.

ES5의 Object.create를 사용하기

function User(name, age){
	var self=. this instanceof User ? this : Object.create(User.prototype);
	self.name = name;
	self.age = age;
	return self;
}

Object.create를 사용하여 prototype을 직접 지정한 객체를 사용하여 반환하였다.

Object.create를 사용할 수 없을 때

if(typeof Object.create === 'undefined'){
		Object.create = function(prototype){
			function C(){}
			c.prototype = ptototype;
			return new C();
		
}

실제 Object.create() 함수는 가변인자를 사용하지만 여기서는 prototype만 설정할 수 있게 해두었다.

생성자 함수 내에서 명시적으로 return 을 실행할 경우 new표현식의 결과오버라이딩하도록 허용하기 때문이다. 이게 무슨말인지 코드로 살펴보자

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

var person = new Person('Alice');
console.log(person) // Person{name:'Alice'}

return 으로 42를 반환하고 있지만 호출 결과는 여전히 Person의 인스턴스가 된다. 42는 무시되고 생성자 함수가 정의한대로 this에 바인딩 된 객체가 새성된다.

function Person(name) {
  this.name = name;
  return { age: 30 }; // 생성자 함수 내에서 객체를 반환
}

var person = new Person('Alice');

console.log(person); // { age: 30 }

이 경우에는 return으로 반환한 { age: 30 }이 반환된다. 리턴값으로 객체를 반환하기 때문이다. 이러한 동작을 오버라이딩 이라고 한다.

문서화하기

생성자 함수는 new를 통해 호출되어야함을 문서화 하면 또한 오류를 방지할 수 있다.



기억할 점

  • 자기 자신을 new로 다시 호출하거나 Object.create를 사용해서 생성자가 호출자의 문법에 관계없이 동작할 수 있게 하자
  • 함수가 new로 호출되기를 기대한다면, 이에 대해 명백하게 문서화 하자
profile
frontend developer

0개의 댓글