[Front] 자바스크립트의 scope-safe constructors

자바스크립트에서 객체를 생성할 때는 new 연산자를 이용해서 새로 인스턴스를 만든다.
객체는 함수다. new 연산자를 쓰지 않는다면 단순한 함수만 실행시킬 뿐이다. 그래서 new 연산자를 쓰지 않고 객체를 쓴다면 strict모드에서는 에러가 날 뿐만아니라 this 객체의 혼동, 프로토타입을 상속 받을 수 없는 등 혼란이 일어나게 된다. 아래 코드를 보자. Person이라는 객체가 있다. 이 객체를 new연산자를 쓸 때와 안쓸때를 비교해보자.

var Person = function(name){
    this.name = name;
};
Person.prototype.sayName = function() {
    console.log(this.name);  
};

var p1 = Person('hou');
var p2 = new Person('hou2');

p1은 new 연산자를 사용하지 않고 p2는 new 연산자를 사용해서 객체를 생성하였다. p1에 할당된 값은 undefined이다. p1은 Person의 프로퍼티를 상속받는것이 아니라 단순히 Person의 생성자 함수 값을 실행시키는 것이기 때문이다. Person객체가 아니여서 프로퍼티 또한 쓸수가 없다. 또한, p1함수 내부의 this값은 window 객체를 가르킨다. 그래서 this.name은 window.name이 된다. 이러한 스코프의 혼동을 방지하기 위해 new연산자를 이용해서 객체를 생성해야 하는것이다.

console.log(p1 instanceof Person); //false

console.log(typeof p1); //undefined

console.log(name); //hou


console.log(p2 instanceof Person); //true

console.log(typeof p2); //object

console.log(name); //hou (this.name값)

만약 이렇게 new 연산자 없이 호출하는 방식도 허용해주고 싶다고 하면 어떻게 해야 할까? 이럴땐, 스코프의 this가 무엇을 가르키는지 보고 분기처리를 해주면 된다. new 연산자로 생성했다면 this는 Person객체의 instance를 가르키고 아니라면 window혹은 다른 스코프를 가르키기 때문에 new연산자로 생성한 값을 return해주면 된다.

var Person = function(name){
    if(this instanceof Person){ //new 연산자로 생성했을 경우 

        this.name = name;
    } else {
        return new Person(name);
    }
}

var p1 = Person('hou');
var p2 = new Person('hou2');

이제 위의 p1과 p2는 같은 방식으로 동작할 것이다. 이미 자바스크립트 언어에는 Object, Array, RegExp, Error등 여러 타입이 어느 스코프에서든 안전하게 사용할 수 있게 되어있다.

var arr1 = Array(1,2,3);
var arr2 = new Array(1,2,3);
console.log(arr1); //[1,2,3]

console.log(arr2); //[1,2,3]
  • 이 포스팅은 객체지향 자바스크립트의 원리(니콜라스 C. 자카스지음, 김태곤 옮김)의 일부를 읽고 정리한 내용입니다.

Comments

comments powered by Disqus
comments powered by Disqus