[디자인 모델] 자 바스 크 립 트 갈고리 메커니즘 의 응용 장면 과 실현

우리 가 비교적 복잡 한 전단 프로젝트 에 직면 할 때, 우 리 는 자주 모듈 화 된 방식 으로 자 바스 크 립 트 코드 를 결합 시 켜 코드 에 대한 관리 와 유지 보 수 를 편리 하 게 한다. 다음은 간단 한 즉시 실행 함수 가 실현 하 는 모듈 화 예 이다.
var Common = (function(){
    var func = function(){
        //       
    }
    return {
        func : func
    }
})();

var ModuleA = (function(){
    var _count = 1;
    var init = function(){
        //       
    }
    var getCount = function(){
        return _count;
    }
    return {
        init : init,
        getCount : getCount
    }
})();

모듈 은 외부 에 필요 한 인터페이스 만 외부 에 노출 되 고 외부 모듈 은 내부 의 운행 논리 에 관심 을 가 질 필요 가 없다. 인 터 페 이 스 를 호출 하 는 방식 과 결 과 를 되 돌려 주 는 것 만 알 면 모듈 의 '저 결합, 고 내 집적' 을 실현 할 수 있다.
보기 에는 아름 답지 만 프로젝트 의 논리 가 점점 복잡 해 질 때 예 를 들 어 A 모듈 에서 전체적인 공용 을 대상 으로 하 는 논리 가 B 모듈 의 특정한 상황 에서 추가 적 인 논리 조작 이 필요 할 수 있 습 니 다. 어떻게 해 야 합 니까?
var Common = (function(){
    var func = function(){
        //       
        if(typeof ModuleA != 'undefined' && ModuleA.getCount() > 0){
            //   A           
        }
    }
    return {
        func : func
    }
})();

var ModuleA = (function(){
    var _count = 1;
    var init = function(){
        //       
    }
    var getCount = function(){
        return _count;
    }
    return {
        init : init,
        getCount : getCount
    }
})();

Common. func 중간 에 있 는 그 덩어리 를 보 았 을 때 갑자기 소 리 를 지 르 지 않 았 을 까? "와, 니 마 왜 이렇게 징 그 러 워!" =
A 모듈 의 논리 인 데 공용 모듈 에 징 그 럽 게 나타 나 는데 이런 특수 논리 가 많아 지면 Common 모듈 이 이렇게 되 지 않 을 까?
var Common = (function(){
    var func = function(){
        //       
        if(typeof ModuleA != 'undefined' && ModuleA.getCount() > 0){
            //   A           
        }
        if(typeof ModuleB != 'undefined' && ModuleB.getWhat() != 'something'){
            //   B           
        }
        // ...
        if(typeof ModuleZ != 'undefined' && ModuleB.isWhat() !== false){
            //   Z           
        }
    }
    return {
        func : func
    }
})();

세상 에, 정말 참 을 수가 없어.
하면, 만약, 만약...만약 이러한 갈고리 (Hook) 가 있다 면, 추가 논리 코드 를 Common. func 에 걸 수 있 고, Common. func 가 실행 하 는 김 에 갈고리 에 걸 려 있 는 코드 도 실행 할 수 있다 면 얼마나 좋 을 까.이렇게 하면 특수 한 추가 조작 을 실현 할 수 있 을 뿐만 아니 라 모듈 의 낮은 결합 과 높 은 내부 집적 도 유지 할 수 있다.
var Common = (function(){
    var func = function(){
        //                      
        Hook.doActions();
        //       
    }
    return {
        func : func
    }
})();

var ModuleA = (function(){
    var _count = 1;
    var init = function(){
        //            Common.func 
        Hook.addAction(Common.func, function(){
            if(_count > 0){
                //          
                console.log('      ?');
            }
        });
        //       
    }
    var getCount = function(){
        return _count;
    }
    return {
        init : init,
        getCount : getCount
    }
})();

아니, 그 럴 리 가 없어.WordPress 의 Hook 메커니즘 을 참고 하여 자 바스 크 립 트 갈고리 메커니즘 모듈 을 바탕 으로 실현 되 었 다.
물론 완전한 갈고리 체 제 는 위 에서 말 한 것 처럼 그렇게 간단 하지 않 습 니 다. 구체 적 으로 실현 하 는 것 은 여러분 이 코드 를 보 거나 보기 싫 은 것 은 스스로 실현 할 수 있 습 니 다. 저 는 군말 하지 않 겠 습 니 다.
/** *     (             ,               ) * * @author Lanfei * @date 2013.10.28 * * function handler(num1, num2){ * Hook.doActions(); * var value = num1 + num2; * return Hook.applyFilters(value); * } * console.log('before hook:'); * console.log(handler(1, 2)); * function action(num1, num2){ * console.log('the numbers are ' + num1 + ' and ' + num2 + '.'); * } * function filter(value){ * return 'the result is ' + value + '.'; * } * Hook.addAction(handler, action); * Hook.addFilter(handler, filter); * console.log('after hook: '); * console.log(handler(1, 2)); * */

var Hook = (function(){

    var addAction = function(method, action, priority){
        _initHook(method);
        var actions = method['__hooks__'].actions;
        actions.push({
            action : action,
            priority : priority || 10
        });
        actions.sort(_compare);
    }

    var doActions = function(){
        var method = Hook.doActions.caller;
        _initHook(method);
        var actions = method['__hooks__'].actions;
        if(arguments.length == 0){
            arguments = method.arguments;
        }
        for(var i in actions){
            if(actions[i].action.apply(method, arguments) === false){
                return false;
            }
        }
    }

    var hasAction = function(method, action){
        _initHook(method);
        var actions = method['__hooks__'].actions;
        if(actions.length > 0 && action !== undefined){
            for(var i in actions){
                if(actions[i].action == action){
                    return true;
                }
            }
            return false;
        }else{
            return actions.length > 0;
        }
    }

    var removeAction = function(method, action){
        _initHook(method);
        var actions = method['__hooks__'].actions;
        if(actions.length > 0){
            if(action !== undefined){
                for(var i in actions){
                    if(actions[i].action == action){
                        delete actions[i];
                        return;
                    }
                }
            }else{
                method['__hooks__'].actions = [];
            }
        }
    }

    var addFilter = function(method, filter, priority){
        _initHook(method);
        var filters = method['__hooks__'].filters;
        filters.push({
            filter : filter,
            priority : priority || 10
        });
        filters.sort(_compare);
    }

    var applyFilters = function(value){
        var method = Hook.applyFilters.caller;
        _initHook(method);
        var filters = method['__hooks__'].filters;
        for(var i in filters){
            value = filters[i].filter.call(method, value);
        }
        return value;
    }

    var hasFilter = function(method, filter){
        _initHook(method);
        var filters = method['__hooks__'].filters;
        if(filters.length > 0 && filter !== undefined){
            for(var i in filters){
                if(filters[i].filter == filter){
                    return true;
                }
            }
            return false;
        }else{
            return filters.length > 0;
        }
    }

    var removeFilter = function(method, filter){
        _initHook(method);
        var filters = method['__hooks__'].filters;
        if(filters.length > 0){
            if(filter !== undefined){
                for(var i in filters){
                    if(filters[i].filter == filter){
                        delete filters[i];
                        return;
                    }
                }
            }else{
                method['__hooks__'].filters = [];
            }
        }
    }

    var _compare = function(hook1, hook2){
        return hook1.priority < hook2.priority;
    }

    var _initHook = function(method){
        if(! method['__hooks__']){
            method['__hooks__'] = {
                actions : [],
                filters : []
            };
        }
    }

    return {
        addAction : addAction,
        doActions : doActions,
        hasAction : hasAction,
        removeAction : removeAction,
        addFilter : addFilter,
        applyFilters : applyFilters,
        hasFilter : hasFilter,
        removeFilter : removeFilter
    };
})();

ps: 원문 주소:http://www.clanfei.com/2013/10/1730.html/comment-page-1

좋은 웹페이지 즐겨찾기