돌아가기

동일한 생성자 함수로 객체 만들기

중요도: 5

생성자 함수가 하나 있고, 이 생성자 함수를 사용해 만든 임의의 객체 obj가 있다고 가정해봅시다. 지금은 이 생성자 함수를 사용해 새로운 객체를 만들어야하는 상황입니다.

정체를 모르는 생성자 함수를 사용해 새로운 객체를 만드는게 가능할까요?

let obj2 = new obj.constructor();

위와 같은 코드를 사용해 객체를 만들 수 있게 해주는 생성자 함수를 작성해보세요. 여기에 더하여 위와 같은 코드가 동작하지 않도록 하는 예시도 하나 만들어보세요.

"constructor" 프로퍼티에 제대로 된 값이 저장되어있다면 위와 같은 접근법이 가능합니다.

기본 "prototype"를 변경하지 않았다면 아래 예시는 의도한 대로 동작합니다.

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

let user = new User('John');
let user2 = new user.constructor('Pete');

alert( user2.name ); // Pete (잘 동작하네요!)

User.prototype.constructor == User이기 때문에 위 예시는 제대로 동작합니다.

그런데 누군가가 User.prototype를 덮어쓰고 User를 참조하는 constructor를 다시 만들어주는 걸 잊었다면 문제의 접근법은 실패합니다.

예시:

function User(name) {
  this.name = name;
}
User.prototype = {}; // (*)

let user = new User('John');
let user2 = new user.constructor('Pete');

alert( user2.name ); // undefined

user2.nameundefined가 될까요?

그 이유는 new user.constructor('Pete')가 아래와 같이 동작하기 때문입니다.

  1. new user.constructor('Pete')user에서 constructor를 찾는데 아무것도 찾지 못합니다.
  2. 객체에서 원하는 프로퍼티를 찾지 못했기 때문에 프로토타입에서 검색을 시작합니다. user의 프로토타입은 User.prototype인데, User.prototype은 빈 객체입니다.
  3. User.prototype은 일반 객체 {}이고, 일반 객체의 프로토타입은 Object.prototype입니다. Object.prototype.constructor == Object이므로 Object가 사용됩니다.

결국에 let user2 = new user.constructor('Pete');let user2 = new Object('Pete')가 됩니다. 그런데 Object의 생성자는 인수를 무시하고 항상 빈 객체를 생성합니다. 따라서 let user2 = new Object('Pete')let user2 = {}와 같다고 생각할 수 있습니다. user2.nameundefined인 이유가 여기에 있습니다.