19

関数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特定の関数ではありませんが、私が扱っている多くの関数です。ページ内で動的に変化することはありません。ただし、それらは時々変更される可能性があります(たとえば、フォームの検証要求)。

解決策:Adam'sAnswerの修正版に落ち着きました。それは完璧ではありませんが、私が持っていたものよりも優れています:

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

NB。.apply()メソッドを持たないIE6/7のいくつかのネイティブ関数に注意してください。

4

5 に答える 5

35

fooオリジナルを呼び出すカスタム関数でオーバーライドできます。

例えば

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

fooまた、置換関数を介して引数を取る必要があります。

于 2012-06-27T09:09:10.357 に答える
7
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*/});

これにより、両方の関数で同じ「これ」が得られます

于 2012-06-27T09:05:56.433 に答える
6

あなたはこのようなことをすることができます:デモ

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();
于 2012-06-27T09:09:40.653 に答える
3

うーん、これは私にも関係します、あなたはそれを言いました

私は定期的にこの状況にあります(そして私はそれを嫌います)。

これがどのようなシナリオで発生し続けるのか聞いてもよろしいですか?それは企業規模ですか、それとも個人的なプロジェクト範囲ですか?あなたは明らかに肩に水平な頭を持っていて、あなたがしていることが普通ではないことを知っているので、私は別の解決策があるかどうか疑問に思っています。

私が尋ねる理由は; このアプローチは潜在的に問題の缶を開く可能性があります。fooたとえば失敗した場合、または評価の途中で値を返した場合はfooどうなりますか?実際の関数に追加barするだけでは、実行されるとは限りません。一方、プリペンディングは実行される可能性が高いことを意味しますが、それでも私の意見では良いアプローチではありません。

機能の見直しを検討しましたfooか?これはばかげた質問のように思えるかもしれませんが、全体を通して同様の問題が発生している場合は、それだけの価値があるかもしれません。物事を抽象化しておきたい場合は、「イベントハンドラー」アプローチを採用できます。これによりfoo、でイベントがトリガーされ、window次にトリガーbarされます。これは、あなたの場合に機能します。

または、それが何であるか、そしてそれが何をするかを知っている場合foo、それがオブジェクトである場合はそのプロトタイプにフックし、そこでコードを適切に修正することができます。ただし、この関数は変更される可能性があるため、このオプションが冗長になる可能性があるとおっしゃいましたが、それでも解決策として考えられます。

于 2012-06-27T09:05:18.210 に答える
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
于 2013-11-15T12:50:03.287 に答える