속깊은 자바- 함수 기반 데코레이터
by parksd
HTML
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
JavaScript
(function() {
var monitorTool,
car,
wrapperFunction;
// 모니터링 툴?
monitorTool = (function() {
var functionSequence = [];
return {
// 데코레이터에 대한 이름과 함수를 저장해 놓는다.
decorate: function(name, func) {
functionSequence.push({
name: name,
func: func
});
},
// 각 데코레이터 함수를 한번씩 실행한다.
monitor: function(func) {
var length = functionSequence.length;
for (i = 0; i < length; i++) {
functionSequence[i].func.apply(this, arguments);
}
}
};
}());
// 다음 3개를 데코레이터로 정의한다.
monitorTool.decorate("before", function(func) {
console.log(func.name + " function has started at " + Date.now());
});
monitorTool.decorate("decorated", function(func) {
func.apply(this, Array.prototype.slice(arguments, 1));
});
monitorTool.decorate("after", function(func) {
console.log(func.name + " function has finished at " + Date.now());
});
// wrapperFunction은 각 데코레이터 함수를 한번씩 호출하는 것.
wrapperFunction = monitorTool.monitor;
car = {
beep: function beep() {
console.log("원래의 beep()");
},
brake: function brake() {
console.log("원래의 brake()");
},
accelerator: function accelerator() {
console.log("원래의 accelerator()");
}
};
// 함수를 wrapper로 wrapping한다.
function wrap(func, wrapper) {
// 원래 함수를 args[0]에 넣고, wrapper 3개를 호출하는 함수를 리턴한다.
// 지금 호출되는게 아니다.
return function() {
var args = [func].concat(Array.prototype.slice.call(arguments));
return wrapper.apply(this, args);
};
}
// 객체가 가진 모든 함수를 wrapper로 wrapping한다.
function wrapObject(obj, wrapper) {
console.log("333");
var prop;
// obj의 속성들에 대해서, function일 경우에만 wrap() 한 다음 다시 저장.
for (prop in obj) {
if (obj.hasOwnProperty(prop) && typeof obj[prop] === "function") {
obj[prop] = wrap(obj[prop], wrapper);
}
}
}
// car 객체를 wrapperFunction 함수로 wrapping하는데, 그 것은 MonitorTool.monitor 함수이다.
//...