클래스 지향 디자인패턴
new
나 instanceof
등 클래스와 비슷하게 생긴 구문도 있고 ES6부터는 아예 class
라는 키워드가 명세에 정식적으로 추가됐지만, 사실 클래스는 없다.new
키워드를 앞에 붙여 생성자를 호출한다.super
키워드를 사용한다.function mixin(sourceObj, targetObj) {
for (var key in sourceObj) {
if (!key in targetObj) {
targetObj[key] = sourceObj[key];
}
}
return targetObj;
}
var Vehicle = {
engines: 1,
ignition: function() {
console.log("엔진을 켠다.")
},
drive: function() {
this.ignition();
console.log("방향을 맞추고 앞으로 간다!");
}
};
var Car = mixin(Vehicle, {
wheels: 4,
drive: function() {
Vehicle.drive.call(this);
console.log(this.wheels + "개의 바퀴로 굴러간다!");
}
});
Car
에는 Vehicle
에서 복사한 프로퍼티와 함수 사본이 있다.Car
에는 이미 자체 drive
프로퍼티가 있으므로 이 프로퍼티 레퍼런스는 오버라이드되지 않는다.Vehicle.drive.call(this)
와 같은 코드를 명시적 의사다형성이라 부른다.drive()
란 이름의 함수가 Vehicle
과 Car
양쪽에 모두 있을 때 이 둘을 구별해서 호출하려면 절대적인 레퍼런스를 이용할 수밖에 없고 그래서 명시적으로 Vehicle
객체의 이름을 지정하여 drive()
함수를 호출한 것이다.Vehicle.drive()
로 함수를 호출하면 this
는 Car
객체가 아닌 Vehicle
객체와 바인딩 되는데, 이때문에 .call(this)
를 붙여 drive()
를 Car
객체의 콘텍스트로 실행하도록 강제한 것이다.var Something = {
cool: function() {
this.greeting = "Hello World";
this.count = this.count ? this.count + 1 : 1;
}
};
Something.cool();
Something.greeting();
Something.count();
var Another = {
cool: function() {
Something.cool.call(this);
}
};
Another.cool();
Another.greeting();
Another.count;
Someting.cool.call(this)
를 하면 Something.cool()
함수를 본질적으로 빌려와서 Another
콘텍스트로 호출한다.Something.call()
의 할당은 Something
이 아닌 Another
다. 따라서 Something
의 작동을 Another
와 섞은 셈이다.this
재바인딩을 십분 활용한 이런 유형의 테크닉은 Something.cool.call(this)
같은 호출이 상대적 레퍼런스가 되지 않아 불안정하므로 사용할 때 신중히 해야한다.