2012-06-27 2 views
15

함수 foo()가 발생할 때마다 함수 bar()를 트리거해야합니다. 함수 foo에 대한 제어권이 없거나 향후 변경 될지 여부는 없습니다. 나는 정기적으로이 상황을 겪는다 (나는 그것을 싫어한다). 기존 함수의 끝에 코드 추가

나는 함수 foo의 끝에 내 코드를 추가하려면이 기능을 썼다

function appendToFunction(fn,code){ 
if(typeof fn == 'function'){ 
    var fnCode = fn.toString() ; 
    fnCode = fnCode.replace(/\}$/,code+"\n}") ; 
    window.eval(fnCode);     // Global scope 
    return true ; 
} 
else{ 
    return false ; 
} 
} 

예 :

appendToFunction(foo,"bar();"); 

이 끔찍한 아이디어로 저를 친다 -하지만 그것은 작동합니다. 누군가 더 나은 (더 안전한) 방향으로 나를 가리켜 주시겠습니까.

편집 : foo은 특정 기능이 아니지만 많은 기능을 다루고 있습니다. 페이지에서 동적으로 변경되지는 않습니다. 그러나 수시로 변경 될 수 있습니다 (예 : 양식 유효성 확인 요구).

솔루션 : 나는 아담의 대답의 수정 된 버전에 정착했다. 완벽하지는 않지만 내가 갖고있는 것보다 낫습니다.

var oldFoo = foo ; 
foo = function(){ 
     var result = oldFoo.apply(this, arguments); 
     bar(); 
     return result ; 
} 

NB. .apply() 메서드가없는 IE6/7의 일부 원시 함수를 조심하십시오. 이뿐만 아니라 저를 염려

+0

중복 가능성 (http://stackoverflow.com/questions/9134686/adding-code-to- :
일반적인 예는 다음 일 수 a-javascript-function-programatically) –

답변

24

에 그냥 원본을 호출하는 사용자 정의 기능을 foo을 무시할 수 같은 줄 것이다.

예.

var old_foo = foo; 
foo = function() { 
    old_foo(); 
    bar(); 
} 

당신은 또한 당신의 교체 기능을 통해 고려합니다 foo 인수를 전달해야합니다.

+0

내 것보다 더 간단하고 조금 안전합니다. 'arguments'와'return'에 대한 변경으로 이것은 대부분의 경우에 효과가있을 것입니다. – ColBeseder

+0

이 솔루션을 사용하면 스택 오버플로가 발생합니다. 동일한 경험이 있다면 아래 xdazz 솔루션이 저에게 효과적입니다. – Observer

3

흠, 당신은 내가 정기적으로이 상황을

언급 (그리고 나는 그것을 싫어한다).

이 시나리오가 계속 발생하는지 묻는다면 어떨까요? 기업 규모 또는 개인 프로젝트 범위에 있습니까? 당신은 명확하게 당신의 어깨에 수평 머리를 가지고 있고 당신이하고있는 것이 평범하지 않다는 것을 알고 있습니다. 그래서 대안의 해결책이 있는지 궁금합니다.

내가 묻는 이유는 다음과 같습니다. 이 접근법은 잠재적으로 문제를 야기 할 수 있습니다. 예를 들어 foo이 실패하거나 foo 값이 중간 평가 값을 반환하면 어떻게됩니까? 실제 함수에 bar을 단순히 추가한다고해서 실행이 보장되는 것은 아닙니다. 다른 한편으로는 그것을 미리 보류하고있는 것은 그것이 이라는 것을 의미하며, 실행될 가능성이있는 일지는 모르겠지만, 여전히 내 의견으로는 좋은 접근 방법이 아닙니다.

foo 기능을 수정 해 보셨습니까? 이것은 어리석은 질문처럼 보일 수도 있지만 비슷한 문제가 생길 때마다 가치가있을 것입니다. 당신이 추상적 인 것을 유지하고 싶다면 foowindow에서 이벤트를 일으키고 다시 bar을 발생시키는 "이벤트 핸들러"접근 방식을 채택 할 수 있습니다.

foo이 무엇인지 알고 무엇을하는지 알았 으면 그것이 객체라면 프로토 타입에 연결 한 다음 코드를 적절히 수정하면됩니다. 그러나이 함수는 변경하기 쉽기 때문에이 옵션을 중복시킬 수는 있지만 가능한 솔루션입니다.이 같은

+0

그것은 (다중) 기업 규모에 있고, 나는'foo' 함수에 대한 통제권이 없습니다. 다른 해결 방법이 있습니다 (예 : 함수의 결과를 확인하는 setTimeout). 하지만 창문에서 이벤트를 실행하면 내가 가진 것에 약간의 개선이 있다고 생각합니다. – ColBeseder

6
function extend(fn,code){ 
    return function(){ 
    fn.apply(fn,arguments) 
    code.apply(fn,argumnets) 
    } 
} 

및 사용은 :

function appendToFunction(fn,code){ 
    if(typeof fn == 'function'){ 
     var fnCode = fn.toString() ; 
     fnCode = fnCode.replace(/\}$/,code+"\n}") ; 
     window.eval(fnCode);     // Global scope 
     return true ; 
    } 
    else{ 
     return false ; 
    } 
} 

appendToFunction = extend(appendToFunction,function(){/*some code*/}); 

이 당신에게 "이"두 기능

6

THE DEMO과 같은 작업을 수행 할 수 있습니다.

function foo() { 
console.log('foo'); 
} 

function appendToFunction(fn, callback) { 
    window[fn] = (function(fn){ 
    return function() { 
     fn(); 
     callback(); 
    } 
}(window[fn])); 
} 

appendToFunction('foo', function(){console.log('appended!')}); 

foo(); 
1

당신은 추가하거나 그들을 예를 들어 사용 병합 기존 기능에 몇 가지 새로운 코드를 붙일 수 있습니다

:

function mergeFunctions(function1, function2, instance1, instance2, numberOfArgumentsToPassToFunc1) { 
    return function() { 
     var _arguments = Array.prototype.slice.apply(arguments); 
     var _arguments1 = _arguments.slice(0, numberOfArgumentsToPassToFunc1); 
     var _arguments2 = _arguments.slice(numberOfArgumentsToPassToFunc1); 
     var that = this; 
     (function(function1, function2) { 
      if (typeof function1 == "function") { 
       if (typeof instance1 != "undefined") { 
        function1.apply(instance1, _arguments1); 
       } 
       else if (that == window) { 
        function1.apply(function1, _arguments1); 
       } 
       else { 
        var compare = mergeFunctions(function(){}, function(){}); 
        if (that.toString() == compare.toString()) { 
         function1.apply(function1, _arguments1); 
        } 
        else { 
         function1.apply(that, _arguments1); 
        } 
       } 
      } 
      if (typeof function2 == "function") { 
       if (typeof instance2 != "undefined") { 
        function2.apply(instance2, _arguments2); 
       } 
       else if (that == window) { 
        function2.apply(function2, _arguments2); 
       } 
       else { 
        var compare = mergeFunctions(function(){}, function(){}); 
        if (that.toString() == compare.toString()) { 
         function2.apply(function2, _arguments2); 
        } 
        else { 
         function2.apply(that, _arguments2); 
        } 
       } 
      } 
     })(function1, function2); 
    } 
} 



기본적인 예는은 다음이 될 것입니다

// Original function: 
var someFunction = function(){ 
    console.log("original content"); 
}; 

// Prepend new code: 
// -------------------------------------------------------- 
someFunction = mergeFunctions(function() { 
    console.log("--- prepended code"); 
}, someFunction); 

// Testing: 
someFunction(); 

// Outout: 
// [Log] --- prepended code 
// [Log] original content 


// Append new code: 
// -------------------------------------------------------- 
someFunction = mergeFunctions(someFunction, function() { 
    console.log("appended code"); 
}); 

// Testing: 
someFunction(); 

// Output: 
// [Log] --- prepended code 
// [Log] original content 
// [Log] appended code 



참고 병합 기능은 병합 된 부분에 예상 한 'this'를 적용하려고 시도합니다. 그렇지 않으면 상대적인 인수를 처리 할 수있을뿐만 아니라 원하는 'this'를 전달할 수 있습니다. [자바 스크립트 기능을 추가, 프로그램 코드]의

function firstPart(a, b) { 
    console.log("--- first part"); 
    console.log("'this' here is:"); 
    console.log(this.name); 
    console.log("a: "+a); 
    console.log("b: "+b); 
} 

function MyObject() { 
    this.x = "x property of MyObject"; 
} 

MyObject.prototype.secondPart = function (y) { 
    console.log(""); 
    console.log("--- second part"); 
    console.log("'this' here is:"); 
    console.log(this.name); 
    this.x = y; 
    console.log("x: "+this.x); 
} 

MyObject.prototype.merged = mergeFunctions(firstPart, MyObject.prototype.secondPart, firstPart, MyObject, 2); 

// Testing 
var test = new MyObject(); 
test.merged("a parameter", "b parameter", "x parameter overrides x property of MyObject"); 

// Console output: 
// [Log] --- first part 
// [Log] 'this' here is: 
// [Log] firstPart 
// [Log] a: a parameter 
// [Log] b: b parameter 
// [Log] 
// [Log] --- second part 
// [Log] 'this' here is: 
// [Log] MyObject 
// [Log] x: x parameter overrides x property of MyObject 
관련 문제